RecyclerView: असंगति का पता चला। अमान्य आइटम स्थिति


271

हमारे क्यूए ने एक बग का पता लगाया है: जब एंड्रॉइड डिवाइस (Droid टर्बो) को घुमाते हुए, निम्नलिखित RecyclerView- संबंधित दुर्घटना हुई:

java.lang.IndexOutOfBoundsException: असंगतता का पता चला। अमान्य आइटम स्थिति 2 (ऑफ़सेट: 2) .स्टेट: 3

मेरे लिए, यह RecyclerView के अंदर एक आंतरिक त्रुटि की तरह दिखता है, क्योंकि मैं इसके किसी भी तरीके के बारे में सीधे हमारे कोड के कारण नहीं सोच सकता ...

किसी को भी इस समस्या का सामना करना पड़ा है?

समाधान क्या होगा?

एक क्रूर वर्कअराउंड अपवाद को पकड़ने के लिए शायद हो सकता है जब ऐसा होता है और एक दूषित स्थिति के साथ छोड़ देने से बचने के लिए, पुनर्चक्रण दृश्य को फिर से बनाएं।

लेकिन, यदि संभव हो, तो मैं समस्या को बेहतर तरीके से समझना चाहूंगा (और शायद इसे अपने स्रोत पर ठीक कर सकता हूं), बजाय इसे मास्क करने के।

बग को पुन: पेश करना आसान नहीं है, लेकिन ऐसा होने पर यह घातक है।

पूर्ण स्टैक-ट्रेस:

W/dalvikvm( 7546): threadid=1: thread exiting with uncaught exception (group=0x41987d40)
    E/AndroidRuntime( 7546): FATAL EXCEPTION: main
    E/AndroidRuntime( 7546): Process: com.oblong.mezzedroid, PID: 7546
    E/AndroidRuntime( 7546): java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 2(offset:2).state:3
    E/AndroidRuntime( 7546):    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3382)
    E/AndroidRuntime( 7546):    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3340)
    E/AndroidRuntime( 7546):    at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1810)
    E/AndroidRuntime( 7546):    at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1306)
    E/AndroidRuntime( 7546):    at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1269)
    E/AndroidRuntime( 7546):    at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:523)
    E/AndroidRuntime( 7546):    at org.liboid.recycler_view.RecyclerViewContainer$LiLinearLayoutManager.onLayoutChildren(RecyclerViewContainer.java:179)
    E/AndroidRuntime( 7546):    at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:1942)
    E/AndroidRuntime( 7546):    at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2237)
    E/AndroidRuntime( 7546):    at org.liboid.recycler_view.LiRecyclerView.onLayout(LiRecyclerView.java:30)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
    E/AndroidRuntime( 7546):    at com.oblong.mezzedroid.workspace.content.bins.BinsContainerLayout.onLayout(BinsContainerLayout.java:22)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
    E/AndroidRuntime( 7546):    at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    E/AndroidRuntime( 7546):    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    E/AndroidRuntime( 7546):    at android.view.View.layout(View.java:14946)
    E/AndroidRuntime( 7546):    at android.view.ViewGroup.layout(ViewGroup.java:4651)
    E/AndroidRuntime( 7546):    at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2132)
    E/AndroidRuntime( 7546):    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1872)
    E/AndroidRuntime( 7546):    at andro

2
एक सवाल: आपका रेप्रो कितनी संगत है? मुझे पता है कि यह यहाँ और यहाँ गूगल के कोड में एक त्रुटि है । लेकिन इससे बचा जा सकता है। तो क्या हर चक्कर पर ऐसा हो रहा है?
विकु

नमस्ते। यह केवल शायद ही कभी होता है, लेकिन जब ऐसा होता है, तो यह ऐप के लिए घातक है।
करोलदीपका

बग के लिंक के लिए धन्यवाद। पहला वाला दूसरे की तुलना में अधिक प्रासंगिक लगता है।
करोलदीपका

1
हाँ, मुझे लगता है कि आपका सबसे अच्छा दांव सिर्फ रोटेशन के दौरान सूची में बदलाव की अनुमति नहीं देना है।
विकू

1
यदि आप आसानी से पुन: पेश कर सकते हैं, तो मैं सुझाव दूंगा कि 'getItemCount' के लिए सभी नोटों को 'सूचित *' करने से पहले प्रिंट करें ... आपको पता चल सकता है कि आपका आइटम नंबर आपकी मान्यताओं से मेल नहीं खाता है।
रिच एहमर

जवाबों:


209

मेरे पास एक (संभवतः) संबंधित मुद्दा था - एक रिसाइक्लरव्यू के साथ एक गतिविधि का एक नया उदाहरण दर्ज करना, लेकिन एक छोटा एडेप्टर मेरे लिए इस दुर्घटना को ट्रिगर कर रहा था।

RecyclerView.dispatchLayout()कॉल करने से पहले स्क्रैप से आइटम खींचने का प्रयास कर सकते हैं mRecycler.clearOldPositions()। परिणाम यह है कि यह आम पूल से आइटम खींच रहा था जिसमें एडेप्टर आकार से अधिक था।

सौभाग्य से, यह केवल अगर PredictiveAnimationsसक्षम किया जाता है, तो मेरा समाधान उपवर्ग GridLayoutManager( LinearLayoutManagerएक ही समस्या और 'ठीक' है) के लिए था, और supportsPredictiveItemAnimations()गलत वापस करने के लिए ओवरराइड करें:

/**
 * No Predictive Animations GridLayoutManager
 */
private static class NpaGridLayoutManager extends GridLayoutManager {
    /**
     * Disable predictive animations. There is a bug in RecyclerView which causes views that
     * are being reloaded to pull invalid ViewHolders from the internal recycler stack if the
     * adapter size has decreased since the ViewHolder was recycled.
     */
    @Override
    public boolean supportsPredictiveItemAnimations() {
        return false;
    }

    public NpaGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public NpaGridLayoutManager(Context context, int spanCount) {
        super(context, spanCount);
    }

    public NpaGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
        super(context, spanCount, orientation, reverseLayout);
    }
}

4
यह मेरे लिए काम करता है, और भविष्य कहनेवाला एनिमेशन अक्षम करने से आप सभी को एक साथ एनिमेशन नहीं खो सकते हैं। वाहवाही।
रॉबर्ट लिबर्टोर

8
महोदय आपका बहुत बहुत धन्यवाद! LinearLayoutManager के साथ तुरंत काम किया, शायद मुझे दिन बचा रहा था।
लेववेर

8
बहुत बहुत धन्यवाद। यह समाधान LinearLayoutManager के साथ काम किया जाता है।
पृथ्वीराज 5

8
मुझे लगता है कि यह आदमी इस लायक है कि हम उसकी कीमती मदद के सम्मान में एक प्रतिमा का निर्माण करें ... यह वेब पर सबसे खराब प्रलेखित मुद्दे में से एक है, लेकिन ऐसा लगता है कि इस मुद्दे पर देव का सामना बहुत हुआ ... मुझे आश्चर्य है कि आप इसे कैसे पा सकते हैं अगर भविष्यनिष्ठाएं झूठी हैं, तो छोड़ दिया जाए @KasHunt क्योंकि, स्टैकट्रेस बहुत अस्पष्ट है ...
पाड

4
किसी को पता है, कि इस हैक के बिना इसे कैसे ठीक किया जाए? क्योंकि InformDatasetChanged DiffUtil के पक्ष में हटा दिया गया था
एंटोन Shkurenko

83

मेरे मामले में (मेरे डेटा संरचना में डेटा को हटा / डालें) मुझे रीसायकल पूल को साफ़ करने और फिर सेट किए गए डेटा सेट को सूचित करने की आवश्यकता थी!

mRecyclerView.getRecycledViewPool().clear(); mAdapter.notifyDataSetChanged();


6
मैं आम तौर पर यह नहीं कहता, लेकिन आपको बहुत धन्यवाद। मैंने इस दुर्घटना को ठीक करने की कोशिश की है जो तेजी से क्रम में चारों ओर की सूची में वस्तुओं के एक समूह को स्थानांतरित करने पर छिटपुट रूप से होती है। मैं सचमुच इस मुद्दे को हल करने की कोशिश कर रहा है पर शायद एक पूरा सप्ताह बिताया है। मैं कुछ महीनों के लिए इससे दूर चला गया, अपने मस्तिष्क को अलग तरीके से देखने का मौका देने की कोशिश करने के लिए, फिर अपने Google Google प्रयास पर यह पाया। तुम्हें आशीर्वाद देते हैं!
चैंटल ओस्जो

मुझे आपको कुकीज़ का एक टन मिलता है क्योंकि आप उनमें से हर एक के लायक हैं। धन्यवाद।
एंटोनी_स्टैनल

आपको ऐसा क्यों करना है?
दलबुक

9
यह एक बहुत बड़ा ऑपरेशन है जो विचारों को पुनर्चक्रित करने के उद्देश्य को पराजित करता है।
gjsalot

@gjsalot तो अगर मैं इसका उपयोग करता हूं, तो क्या यह कुछ समस्याएं पैदा कर सकता है?
श्रीकांत करुमनघाट

38

इस मामले में notifyDataSetChanged()इसके बजाय notifyItem...का उपयोग करें ।


5
कुछ मामलों में यह जाने का तरीका है। मेरे पास एक ऐसी स्थिति थी जहां मैंने अपने सभी आइटम बदल दिए, लेकिन मैं एडॉप्टर के साथ ईमानदार नहीं था, केवल यह बता रहा था कि मैंने कुछ नए आइटम (InformItemRangeInserted) डाले थे, पहले यह बताए बिना कि मैंने आइटम भी हटा दिए थे। तब एडॉप्टर से उम्मीद की जा रही थी कि वास्तव में और आइटम होंगे। यदि एडाप्टर के अधिसूचित तरीकों में से किसी का उपयोग करते हुए InformDataSetChanged, जैसे कि InformItemRangeRemoved / Inserted / Updated की अपेक्षा की जाती है, तो कॉल करने वाले के पास एडेप्टर को यह बताने की पूरी ज़िम्मेदारी है कि क्या बदला गया था, या आप इस "असंगत स्थिति" के साथ समाप्त हो सकते हैं।
JHH

19
यह बिल्कुल समाधान नहीं है।
21:39 पर मिहा_x64

यह रास्ता नहीं है। यदि यह काम करता है तो इसका मतलब है कि आपने अभी तक के लिए सीमा को गड़बड़ कर दिया है notifyItem...और इसे सुधारना है जो सभी वस्तुओं को फिर से प्रदान करने के बजाय काम करना शुरू कर देगा।
रंजन

12

मैंने mRecycler.setAdapter(itemsAdapter)एडॉप्टर के साथ सभी आइटम्स को जोड़ने के बाद तक देरी करके इसे हल mRecycler.addAll(items)किया और यह काम किया। पता नहीं मैंने ऐसा क्यों शुरू किया, यह एक पुस्तकालय के कोड से था जिसे मैंने देखा और "गलत क्रम" में उन पंक्तियों को देखा, मुझे पूरा यकीन है कि यह हालांकि है, कृपया अगर कोई इसकी पुष्टि कर सकता है कि यह क्यों है? इसलिए? यकीन नहीं होता कि यह एक वैध जवाब है


मुझे लगता है कि यह समाधान है, एक बार जब मैंने एडॉप्टर में देरी की तो यह ठीक था कि मेरा मानना ​​है ... अब यह यूआई थ्रेड में एडॉप्टर सेट करने और उसमें आइटम जोड़ने पर पॉप अप होता है।
16

18
मैंने swapAdapter(adapter, true)इसके बजाय इस्तेमाल किया setAdapter(adapter)और इससे मदद मिली।
17

11

मुझे भी ऐसी ही समस्या थी लेकिन बिल्कुल वैसी ही नहीं। मेरे मामले में 1 बिंदु पर मैं उस सरणी को साफ़ कर रहा था जो कि recyclerview को पारित किया गया था

mObjects.clear();

और जब तक मैं पुनः विचार नहीं करना चाहूँ, मुझे सूचित नहीं करना चाहिए, जैसा कि सूचित करें। मैं AsyncTask में mObjects सरणी को फिर से भर रहा था।


9

मैं recyclerView के साथ एक ही मुद्दा था तो मैं सिर्फ सूची को मंजूरी दे दी के बाद डेटा सेट परिवर्तन के बारे में अनुकूलक अधिसूचित किया।

mList.clear();
mAdapter.notifyDataSetChanged();

mList.addAll(newData);
mAdapter.notifyDataSetChanged();

1
इस साधारण गलती ने मुझे इतना समय खो दिया, बहुत बहुत धन्यवाद!
leb1755

7

मेरे पास एक ही मुद्दा है। यह तब हुआ जब मैं तेजी से स्क्रॉल कर रहा था और एपीआई को कॉल कर रहा था और डेटा को अपडेट कर रहा था। दुर्घटना को रोकने के लिए सभी चीजों की कोशिश करने के बाद, मुझे समाधान मिला।

mRecyclerView.stopScroll();

यह काम करेगा।


यह वर्कअराउंड है न कि फिक्स। आप इसे स्क्रॉल को रोकने के लिए मजबूर कर रहे हैं। बैड यूएक्स
डॉ। एनड्रो

1
@ Dr.aNdRO: एडॉप्टर को स्थिति सेट करने की आवश्यकता होती है और यदि आप पुनरावर्तक स्क्रॉलिंग जारी रखते हैं, तो एडेप्टर डेटा सेट नहीं कर सकता है जो क्रैश का कारण है। यह बुरा नहीं है UX
आनंद सज्जानी

1
सही बात। डेटा रीफ़्रेश होने के बाद से स्क्रॉलिंग रोकना बुरा नहीं है।
सुष

6

मैं RecyclerViewपृष्ठभूमि के लिए डेटा बदल रहा हूं Thread। मुझे Exceptionओपी के समान ही मिला । डेटा बदलने के बाद मैंने इसे जोड़ा:

myRecyclerView.post(new Runnable() {
    @Override
    public void run() {
        myRecyclerAdapter.notifyDataSetChanged();
    }
});

आशा करता हूँ की ये काम करेगा


धन्यवाद दोस्त! यह एकमात्र उत्तर है जो Android विकास के दृष्टिकोण से समझ में आता है।
user347187

जबकि मैंने भी इसकी मदद से हल किया है view.recycler_view.post, मैंने उपयोग किया है notifyItemInserted। मेरे मामले में यह पहले से ही यूआई धागा है।
CoolMind

6

यह त्रुटि तब होती है जब एडाप्टर में सूची स्पष्ट होती है जब उपयोगकर्ता स्क्रॉलिंग जो आइटम धारक की स्थिति को बदलते हैं, सूची और आइटम के बीच ui पर खो जाता है, त्रुटि अगले "नोटिफाइडसेटसेटेड" अनुरोध में होती है।

ठीक कर:

अपनी अद्यतन सूची विधि की समीक्षा करें। अगर आप कुछ ऐसा करते हैं

mainList.clear();
...
mainList.add() or mainList.addAll()
...
notifyDataSetChanged();

===> Error occur

कैसे ठीक करना है। बफर प्रोसेसिंग के लिए नई सूची ऑब्जेक्ट बनाएं और उसके बाद मुख्य सूची पर फिर से असाइन करें

List res = new ArrayList();
…..
res.add();  //add item or modify list
….
mainList = res;
notifyDataSetChanged();

इस महान मदद के लिए नाहन काओ को धन्यवाद :)


4

Adapterसंदर्भ के बजाय आइटम सरणी की एक प्रति का उपयोग करने के लिए मेरे कार्यान्वयन को संशोधित करने के बाद मेरी समस्या दूर हो गई । setItems()विधि हर बार जब हम में दिखाने के लिए नए आइटम नहीं हैं कहा जाता है RecyclerView

के बजाय:

private class MyAdapter extends RecyclerView.Adapter<ItemHolder> {
     private List<MyItem> mItems;  

    (....)

    void setItems(List<MyItem> items) {
        mItems = items;
    }
}

मैंने किया:

void setItems(List<MyItem> items) {
    mItems = new ArrayList<>(items);
}

यह समस्या को हल करेगा, लेकिन इसे मूल मेमोरी से दोगुना नहीं लगेगा?
श्रीकांत करुमनघाट

@ MiguelA.Gabriel यह प्रदर्शन को प्रभावित करेगा? मेरे मामले में उदाहरण के लिए मैं recylerview की सरणी को बहुत बार अद्यतन कर रहा हूं इसलिए वर्तमान में मैं यह कर रहा suggestionsRecyclerView.swapAdapter(new CandidatesAdapter(mSuggestions), true); हूं और यह मेरा रचनाकार हैpublic CandidatesAdapter(List<String> suggestionsList) { this.suggestionsList = new ArrayList<>(suggestionsList); }
Mateen Chaudhry

@ मतेन-चौधरी यह शायद करेंगे। आपको अपने मामले में इसका परीक्षण करना होगा और प्रस्तावित समाधानों में से किसी अन्य का उपयोग करके निर्णय लेना होगा। जैसा कि मैंने कहा, यह केवल एक समाधान है और यह मेरे मामले में मेरे लिए काम करता है।
मिगेल ए। गैब्रियल

3

मैंने उसी स्थिति का सामना किया है। और यह आपके संग्रह को साफ़ करने से पहले कोड जोड़कर हल किया गया था।

mRecyclerView.getRecycledViewPool().clear();


3

मेरे मामले में, मैं notifyDataSetChangedएक गैर-यूआई थ्रेड में आइटम और कॉलिंग को अपडेट कर रहा था । ज्यादातर समय यह काम करता था, लेकिन जब बहुत सारे बदलाव जल्दी हो गए, तो यह दुर्घटनाग्रस्त हो गया। जब मैंने किया, इसके बजाय, मूल रूप से

activity.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        changeData();
        notifyDataSetChanged();
    }
});

तब यह दुर्घटनाग्रस्त हो गया।


3

आपको केवल अपनी सूची को साफ़ करने की आवश्यकता है OnPostExecute()और करते समय नहींPull to Refresh

// Setup refresh listener which triggers new data loading
        swipeContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {

                AsyncTask<String,Void,String> task = new get_listings();
                task.execute(); // clear listing inside onPostExecute

            }
        });

मुझे पता चला कि ऐसा तब होता है जब आप रिफ्रेश करने के लिए एक स्क्रॉल के दौरान स्क्रॉल करते हैं , क्योंकि मैं सूची को क्लियर कर रहा था async task, जिसके परिणामस्वरूप java.lang.IndexOutOfBoundsException: Inconsistency detected.

        swipeContainer.setRefreshing(false);
        //TODO : This is very crucial , You need to clear before populating new items 
        listings.clear();

इस तरह आप एक असंगति के साथ समाप्त नहीं होंगे


2

यह एक ही समय में कई बार एडेप्टर सेट करने से भी संबंधित हो सकता है। मेरे पास एक कॉलबैक विधि थी जो एक ही समय में 5-6 बार ट्रिगर की गई थी और मैं उस कॉलबैक में एडेप्टर सेट कर रहा था ताकि RecycledViewPool उन सभी डेटा के साथ समकालीन रूप से संभाल नहीं सके। यह एक मोटा मौका है, लेकिन आप इसे वैसे भी बेहतर तरीके से देख सकते हैं।


1
हाँ वही समस्या .. लेकिन समाधान? आप केवल कारण देते हैं .. कैसे ठीक करें?
रंजीथ कुमार

@ रंजीथकुमार, उपरोक्त मुद्दे को हल करने के लिए कृपया अपना रास्ता साझा करें। मैंने इसे mRecyclerView.getRecycledViewPool ()। Clear () का उपयोग करके हल किया;
अडॉप्टडसेट के

क्या आप कृपया मेरे कोड पर एक नज़र डाल सकते हैं मुझे लगता है कि मेरी समस्या आपकी तरह है क्या आप मुझे stackoverflow.com/questions/50213362/…
Mateen Chaudhry

2

उपयोग

notifyDataSetChanged()

बजाय

notifyItemRangeInserted(0, YourArrayList.size())

इस मामले में।


1
लेकिन यह प्रदर्शन के लिए सही नहीं है? InformItemRangeInserted बेहतर है, समस्या यहाँ झूठ नहीं है
Derekyy

2

इस समस्या को ठीक करने के लिए, रीसायकल दृश्य को अपडेट करने से पहले बस खाली सूची के साथ InformDataSetChanged () को कॉल करें।

उदाहरण के लिए

//Method for refresh recycle view

    if (!hcpArray.isEmpty())

hcpArray.clear (); // अद्यतन रीसायकल दृश्य के लिए सूची

adapter.notifyDataSetChanged();

2
समाधान नहीं।
मिहा_एक्स ६४

@Milha मुझे क्रैश समस्या को ठीक करने के लिए कोई अन्य समाधान नहीं मिला। लेकिन उपरोक्त समाधान मेरे लिए काम किया है। यदि यह एक समाधान नहीं है तो मुझे उचित समाधान बताएं।
EKN

निर्भर करता है। आप RecyclerView सामग्री को अपडेट करने के लिए एक सामान्य-प्रयोजन उपकरण - डिफ्यूटिल का उपयोग करने का प्रयास कर सकते हैं।
Miha_x64

2

मेरे मामले में मैं बस के साथ लाइन हटा दिया setHasStableIds(true);


लेकिन HasStableIds (सच) आरवी के प्रदर्शन में सुधार करता है, क्या कोई वैकल्पिक समाधान है?
श्रीकांत करुमनघाट

वास्तव में मुझे लगता है कि यह विभिन्न कारणों से हो सकता है, इसलिए इस समस्या के विभिन्न कारण हो सकते हैं जो मूल कारण है।
श्रीकांत करुमनघाट

2

मेरे मामले में मैं अपने एडॉप्टर कंटेंट को एक बैकग्राउंड थ्रेड पर बदलने की कोशिश कर रहा था, लेकिन मुख्य / ui थ्रेड पर सूचित करें।

यह संभव नहीं है!मुख्य थ्रेड को सूचित करने के लिए मजबूर करने का कारण यह है कि recyclerview आपको मुख्य थ्रेड पर अपने बैकिंग एडेप्टर को संपादित करना चाहता है, यहां तक ​​कि एक ही कॉल स्टैक पर भी।

समस्या को हल करने के लिए सुनिश्चित करें कि आपके एडाप्टर के साथ-साथ हर ऑपरेशन को सूचित करें ... कॉल ui / मुख्य धागे पर किया गया है !


2
अपने एडॉप्टर में सूची में आइटम जोड़ना एक बैकग्राउंड थ्रेड पर किया जाना चाहिए और पोस्टएक्सक्यूट पर सूचित करें। यूआई थ्रेड में डेटा जोड़ने से ऐप कुछ मिलीसेकंड या सेकंड के लिए फ्रीज हो जाता है यदि कई डेटा जोड़ते हैं
dione llorera

@dionellorera के साथ सहमति व्यक्त की, यह स्पष्ट किया जाना चाहिए कि "एडेप्टर सामग्री में परिवर्तन" का अर्थ विशेष रूप से किसी भी डेटा को सीधे संशोधित करना है, चाहे आदिम मूल्य, वस्तुओं के गुण, या स्वयं वस्तुएं
OzzyTheGiant

2

मैं हाल ही में नए Android आर्किटेक्चर कंपोनेंट्स के साथ इस नॉटी स्टैक ट्रेस में भाग गया। अनिवार्य रूप से, मेरे पास मेरे ViewModel में आइटमों की एक सूची है जो LiveData का उपयोग करते हुए, मेरे टुकड़े द्वारा देखे जाते हैं। जब ViewModel डेटा के लिए एक नया मान पोस्ट करता है, तो फ़्रैगमेंट एडॉप्टर को अपडेट करता है, इन नए डेटा तत्वों में पास होता है और एडेप्टर को सूचित करता है कि परिवर्तन हुए हैं।

दुर्भाग्य से, एडेप्टर में नए डेटा तत्वों में पास होने पर, मैं इस तथ्य के लिए जिम्मेदार नहीं था कि व्यूमॉडल और एडेप्टर दोनों एक ही ऑब्जेक्ट संदर्भ की ओर इशारा करेंगे! मतलब कि अगर मैं डेटा अपडेट करता हूं और कॉल करता हूंpostValue() ViewModel के भीतर से , तो एक बहुत छोटी खिड़की है जहां डेटा अपडेट किया जा सकता है और एडॉप्टर अभी तक अधिसूचित नहीं किया गया है!

एडेप्टर में पास होने पर तत्वों की एक नई प्रति को तुरंत हटाने के लिए मेरा फिक्स था:

mList = new ArrayList<>(passedList);

इस सुपर आसान फिक्स के साथ आपको सुनिश्चित किया जा सकता है कि आपके एडॉप्टर का डेटा तब तक नहीं बदलेगा जब तक आपके एडॉप्टर को सूचित नहीं किया जाता।


2

यह केवल समाधान है जो मेरे लिए काम करता है यहां तक ​​कि उपरोक्त समाधानों में से कई की कोशिश कर रहा है।

1.) गहनता

CustomAdapter scrollStockAdapter = new CustomAdapter(mActivity, new ArrayList<StockListModel>());
list.setAdapter(scrollStockAdapter);
scrollStockAdapter.updateList(stockListModels);

2.) एडॉप्टर में इस विधि को लिखें

public void updateList(List<StockListModel> list) {
stockListModels.clear();
stockListModels.addAll(list);
notifyDataSetChanged();
}

stockListModels -> यह सूची वह है जो आप एडॉप्टर में उपयोग कर रहे हैं।


2

मेरे लिए, इस कोड को जोड़ने के बाद इसने काम किया:

mRecyclerView.setItemAnimator(null);

2
यह ज्यादातर मामलों में एक तय नहीं है, अगर आप एनीमेशन चाहते हैं तो आपके एडेप्टर कोड को फिर से लिखना होगा और परिवर्तनों को सूचित करने में अपनी त्रुटियों को
ढूंढना होगा

यह मेरे लिए ठीक काम करता है। मैं असली अडैप्टर का उपयोग कर रहा हूं ताकि मैं प्रवाह को नियंत्रित न कर सकूं और मैंने विंडो एक्टिविटी ट्रान्सपेंशन को इस शैली में सक्षम किया कि इस मुद्दे का क्या कारण है कि धन्यवाद मेरा दिन आप बचाएं।
अरुल मणि

1

यह समस्या तब हो सकती है जब आप अपनी सूची को साफ़ करने का प्रयास करते हैं, यदि आप अपनी डेटा सूची को विशेष रूप से तब साफ़ करने जा रहे हैं, जब आप बूलियन ध्वज का उपयोग करने के लिए ताज़ा करने के लिए पुल का उपयोग कर रहे हैं, तो इसे गलत के रूप में आरंभ करें और OnRefresh विधि इसे सही करें, अपना डेटा सूची साफ़ करें यदि ध्वज इसमें नया डेटा जोड़ने से ठीक पहले है और इसके बाद इसे गलत बनाते हैं।

आपका कोड इस तरह हो सकता है

 private boolean pullToRefreshFlag = false ;
 private ArrayList<your object> dataList ;
 private Adapter adapter ;

 public class myClass extend Fragment implements SwipeRefreshLayout.OnRefreshListener{

 private void requestUpdateList() {

     if (pullToRefresh) {
        dataList.clear
        pullToRefreshFlag = false;
     }

     dataList.addAll(your data);
     adapter.notifyDataSetChanged;


 @Override
 OnRefresh() {
 PullToRefreshFlag = true
 reqUpdateList() ; 
 }

}

1

मेरा पहले भी यही मुद्दा था। अंत में उस के लिए एक वैकल्पिक हल मिला

एडेप्टर को सूचित करने के लिए मैं क्या करता हूं कि आइटम हटा दिया गया है और फिर एडॉप्टर डेटा सेट सीमा को सूचित करें

 public void setData(List<Data> dataList) {
      if (this.dataList.size() > 0) {
          notifyItemRangeRemoved(0, dataList.size());
          this.dataList.clear();
      }
      this.dataList.addAll(dataList)
      notifyItemRangeChanged(0, dataList.size());

 }

1

मैं एक ऐसे ही मुद्दे पर भागा और यह समझ लिया। मैंने एक परीक्षण मामले के लिए कुछ उदाहरणों को हार्ड-कोडित किया, लेकिन यह सुनिश्चित नहीं किया कि वे प्रत्येक को एक अद्वितीय आईडी लौटाए और जो मेरे लिए नीचे दुर्घटना का कारण बने। आईडी को ठीक करने से समस्या हल हो गई, आशा है कि यह किसी और की मदद करेगा!


1

मुझे एक बार त्रुटि भी मिली:

कारण: मैं पुराने हटाए गए व्यूहोल्डर्स को प्राप्त करने की कोशिश करते हुए एक साथ Async कार्य से एक पुनर्नवीनीकरण दृश्य को अपडेट करने की कोशिश कर रहा था;

कोड: मैं एक बटन के प्रेस पर डेटा उत्पन्न करता हूं, तर्क निम्नानुसार है

  1. पुनरावर्ती दृश्य में अंतिम आइटम साफ़ करें
  2. डेटा उत्पन्न करने के लिए async कार्य को कॉल करें
  3. OnPostExecute Recycler दृश्य और NotifyDataSetChanged अद्यतन करें

समस्या: जब भी मैं अपने डेटा को प्राप्त करने से पहले तेजी से स्क्रॉल करता हूं मुझे मिलता है

असंगति का पता चला। अमान्य दृश्य धारक एडाप्टर स्थितिदृश्य फ़ोल्डर java.lang.IndexOutOfBoundsException: असंगति का पता चला। अमान्य आइटम स्थिति 20 (ऑफ़सेट: 2) .स्टेट: 3

समाधान: मेरे डेटा को उत्पन्न करने से पहले RecyclerView को साफ़ करने के बजाय, मैं इसे छोड़ देता हूं और फिर इसे नए डेटा, कॉल नोटिफ़ाइडसेटेट के साथ बदलें, जैसा कि नीचे दिखाया गया है;

       @Override
        protected void onPostExecute(List<Objects> o) {
            super.onPostExecute(o);
            recyclerViewAdapter.setList(o);
            mProgressBar.setVisibility(View.GONE);
            mRecyclerView.setVisibility(View.VISIBLE);
        }

क्या आप कृपया मेरे कोड पर एक नज़र डाल सकते हैं मुझे लगता है कि मेरी समस्या आपकी तरह है [लिंक] ( stackoverflow.com/questions/50213362/… )
Mateen Chaudhry

1

सूचित करने से पहले अपने लेआउट प्रबंधक के सभी विचारों को हटा दें। पसंद:

myLayoutmanager.removeAllViews();

यह काम करता हैं। मुझे स्क्रॉल लोड और टैब परिवर्तन की समस्या थी।
वार्विक

1

ListAdapter (androidx.recyclerview.widget.ListAdapter)कॉल करने adapter.submitList(null)से पहले कॉल का उपयोग करना adapter.submitList(list):

adapter.submitList(null)
adapter.submitList(someDataList)

0

मैंने पाया कि mRecycler.setLayoutFrozen (सत्य) सेट करना; स्वाइप कॉर्नर की ऑनफ्रेश विधि में।

मेरे लिए समस्या हल हो गई।

swipeContainer.setOnRefreshListener(new   SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            orderlistRecycler.setLayoutFrozen(true);
            loadData(false);

        }
    });

0

यह काफी गंदा बग है।

अपने आइटम क्लिक को संभालने के लिए, मैंने इस प्रश्नRecyclerView.OnItemTouchListener में पाए गए समाधान के समान कार्यान्वयन का उपयोग किया ।

कई बार RecyclerViewडेटा स्रोत को ताज़ा करने और किसी आइटम को क्लिक करने के बाद, यह IndexOutOfBoundsExceptionमेरे एप्लिकेशन को क्रैश कर देगा। जब कोई आइटम क्लिक किया RecyclerViewजाता है , तो आंतरिक रूप से सही अंतर्निहित दृश्य की तलाश में चला जाता है और इसे वापस स्थिति देता है। स्रोत कोड की जाँच करते हुए, मैंने देखा कि कुछ Tasksऔर Threadsनिर्धारित थे । कहानी को छोटा करने के लिए, मूल रूप से यह कुछ अवैध राज्य है जहां दो डेटा स्रोत आपस में जुड़े हुए हैं और सिंक्रनाइज़ नहीं हैं और पूरी बात जंगली हो जाती है।

इस आधार पर, मैं की मेरी कार्यान्वयन हटाया RecyclerView.OnItemTouchListenerऔर बस पर क्लिक पकड़ा ViewHolderके Adapterअपने आप को:

public void onBindViewHolder (final BaseContentView holder, final int position) {

    holder.itemView.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick (View view) {

        // do whatever you like here
      }
    });

}

यह सबसे अच्छा समाधान नहीं हो सकता है, लेकिन अभी के लिए एक दुर्घटना-मुक्त .. उम्मीद है कि यह आपको कुछ समय बचा लेगा :)।


हर बार ऑन लाइन एक नई वस्तु बनाने को कहा जाता है, जिसके परिणामस्वरूप बहुत सारी वस्तुएं एकत्रित हो जाएंगी और उपयोगकर्ता को ठंड का अनुभव हो सकता है।
डेफिनेरा

0

लिंट ने मुझे असंगति से संबंधित एक सलाह दी: मैंने लिखा (onBindViewHolder ()):

pholder.mRlayout.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        doStuff(position);
                    }
                });

जिसे प्रतिस्थापित करना था:

pholder.mRlayout.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        doStuff(pholder.getAdapterPosition());
                    }
                });

अपने कोड में दोनों कोड चलाएं और फिर पूर्ण स्पष्टीकरण के लिए Lint चलाएं !!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.