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




रीसाइक्लिंग क्या है (20)

add_location.removeAllViews ();

 holder.itemLayout.setVisibility( View.GONE );//to hide temprory it show like you have removed item

        Model current = list.get( position );
        list.remove( current );
        list.add( list.size(), current );//add agine to last index
        if(position==list.size()-1){// remove from last index
             list.remove( position );
        }

https://code.i-harness.com

हमारे क्यूए ने एक बग का पता लगाया है: एंड्रॉइड डिवाइस (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

आपको केवल अपनी सूची को 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();

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


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

उदाहरण के लिए

//Method for refresh recycle view

    if (!hcpArray.isEmpty())

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

adapter.notifyDataSetChanged();

उपयोग

notifyDataSetChanged()

बजाय

notifyItemRangeInserted(0, YourArrayList.size())

इस मामले में।


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

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

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

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

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

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

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

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

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

mObjects.clear();

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


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

mRecyclerView.stopScroll();

यह काम करेगा।


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

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

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
      }
    });

}

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

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

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


मेरे मामले में मैंने अभी-अभी setHasStableIds(true); साथ लाइन निकाली setHasStableIds(true);


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

public void add(Data item) {
        if(!params.contains(item){
           params.add(item);
           notifyItemInserted(getItemCount() - 1);
        }
    }
}

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

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

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

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

आशा है ये मदद करेगा


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

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

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

mList = new ArrayList<>(passedList);

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


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

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

 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());

 }

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


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

ठीक कर:

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

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);
}

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


यह समस्या तब हो सकती है जब आप अपनी सूची को साफ़ करने का प्रयास करते हैं, यदि आप अपनी डेटा सूची को विशेष रूप से तब साफ़ करने जा रहे हैं, जब आप बूलियन ध्वज का उपयोग करने के लिए ताज़ा करने के लिए पुल का उपयोग कर रहे हैं, तो इसे गलत के रूप में आरंभ करें और 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() ; 
 }

}

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

के बजाय:

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

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

मैंने किया:

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

===> Error occur

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

myLayoutmanager.removeAllViews();




screen-rotation