RecyclerView:检测到不一致。无效的商品位置


271

我们的质量检查已检测到一个错误:旋转Android设备(Droid Turbo)时,发生了以下与RecyclerView相关的崩溃

java.lang.IndexOutOfBoundsException:检测到不一致。无效的商品位置2(偏移量:2)。状态:3

对我来说,这看起来像是RecyclerView内部的错误,因为我想不出这是由我们的代码直接引起的。

有没有人遇到这个问题?

解决办法是什么?

一个残酷的解决方法可能是在发生异常时捕获异常,然后从头开始重新创建RecyclverView实例,以避免陷入损坏状态。

但是,如果可能的话,我想更好地理解问题(也许从源头上解决它),而不是掩盖它。

该错误不容易重现,但是一旦发生就致命。

完整的堆栈跟踪:

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
一个问题:您的再现性如何?我知道这是这里这里的 google代码中的错误。但这是可以避免的。那么,这是否在每次旋转时发生?
VicVu 2015年

你好 它很少发生,但是一旦发生,对应用程序来说是致命的。
KarolDepka

感谢您提供的错误链接。第一个似乎比第二个更相关。
KarolDepka

1
是的,我认为最好的选择是在轮换期间不允许更改列表视图。
VicVu 2015年

1
如果您可以轻松重现,我建议在所有对“ notify *”的调用之前打印“ getItemCount”的值...您可能会发现您的商品数与您的假设不符。
Rich Ehmer

Answers:


209

我遇到了一个(可能)相关的问题-使用RecyclerView输入活动的新实例,但是使用较小的适配器为我触发了此崩溃。

RecyclerView.dispatchLayout()可以在致电前尝试从废料中取出物品mRecycler.clearOldPositions()。结果是它正在从公共池中提取位置高于适配器大小的项目。

幸运的是,只有PredictiveAnimations启用了它才能执行此操作,所以我的解决方案是子类化GridLayoutManagerLinearLayoutManager具有相同的问题和“修复”),并重写supportsPredictiveItemAnimations()以返回false:

/**
 * 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
这对我有用,并且禁用预测动画不会导致您一起丢失动画。太棒了
罗伯特·利伯托里特2015年

8
先生非常感谢您!立即与LinearLayoutManager一起工作,可能节省了我几天的时间。
levavare

8
非常感谢。此解决方案与LinearLayoutManager一起使用。
Pruthviraj'3

8
我认为这个家伙值得我们为纪念他的宝贵帮助而建造一座雕像...这是网络上记录最烂的问题之一,但是似乎很多开发人员都遇到了这个问题...我只是想知道您是怎么找到它的?如果PredictiveAnimations为假,@KasHunt会被跳过?因为,堆栈跟踪非常不清楚...
PAD 2016年

4
有人知道,如果没有此技巧,该如何解决?因为notifyDatasetChanged被弃用,而转而使用DiffUtil
Anton Shkurenko,

83

就我而言(删除/插入数据结构中的数据),我需要清除回收池,然后通知数据集已更改!

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


6
我通常不会这么说,但是非常感谢您。我已经尝试了所有方法来解决此崩溃问题,该崩溃问题是在我快速移动列表中的一堆项目时偶尔发生的。我实际上已经花了整整一周的时间来尝试解决此问题。我走了几个月,试图让我的大脑有机会尝试不同的方法,然后在我第一次尝试Google时就发现了这一点。祝福你!
Chantell Osejo

让我给你买很多饼干,因为你应该配得上每一个。谢谢。
antonis_st

你为什么要这样做?
dabluck

9
这是一个非常繁重的操作,有损于回收视图的目的。
gjsalot

@gjsalot因此,如果我使用它,会引起一些问题吗?
Sreekanth Karumanaghat

38

在这种情况下,请notifyDataSetChanged()改用notifyItem...


5
在某些情况下,这是要走的路。我遇到了替换所有项目的情况,但是我对适配器不诚实,只是告诉它我插入了一些新项目(notifyItemRangeInserted),而没有先告诉我我也删除了项目。然后,适配器预计会有比实际更多的项目。如果使用适配器的任何notify方法期望notifyDataSetChanged,例如notifyItemRangeRemoved / Inserted / Updated,则调用者有全部责任告诉适配器确切的更改,否则您可能会遇到这种“不一致的状态”。
JHH

19
这根本不是解决方案。
Miha_x64

这不是要走的路。如果此方法有效,则意味着您只是弄乱了范围,notifyItem...并进行了更正,而不是重新渲染所有项目。
Ranjan

12

我通过mRecycler.setAdapter(itemsAdapter)将所有项目添加到适配器后延迟了耕作来解决此问题,mRecycler.addAll(items)并且它可以正常工作。我不知道为什么要这么做,因为我是从图书馆的代码中查看并以“错误的顺序”看到这些行的,但是我很确定是这样,请有人确认它可以解释为什么所以?甚至不确定这是否是有效答案


我认为这是解决方案,一旦我延迟了适配器,那很好,我相信...现在,当在UI线程中设置适配器并向其中添加项目时,它会弹出。
EngineSense 2016年

18
我用swapAdapter(adapter, true)代替,setAdapter(adapter)它有所帮助。
frangulyan '16

11

我有类似的问题,但不完全相同。就我而言,在1点时,我正在清除传递到recyclerview的数组

mObjects.clear();

而不是调用notifyDataSetChanged,因为我不希望recyclerview立即清除视图。我在AsyncTask中重新填充了mObjects数组。


9

我在recyclerView上也遇到了同样的问题,所以我只是在清除列表后立即通知适配器有关数据集更改的信息。

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

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

1
这个简单的错误使我浪费了很多时间,非常感谢!
leb1755 '18

7

我有一个相同的问题。当我快速滚动并调用API并更新数据时发生了这种情况。在尝试了所有方法以防止崩溃后,我找到了解决方案。

mRecyclerView.stopScroll();

会的。


这是一种解决方法,而不是解决方法。您正在强迫它停止滚动。错误的用户体验
aNdRO博士18年

1
@ Dr.aNdRO:适配器需要设置位置,如果继续滚动recylerview,适配器将无法设置导致崩溃的数据。UX还不错
Anand Savjani

1
合理。因为发生数据刷新,所以停止滚动还不错。
Sush

6

我正在RecyclerView后台更改数据Thread。我Exception和OP一样。我在更改数据后添加了此代码:

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

希望能帮助到你


谢啦!从Android开发的角度来看,这是唯一有意义的答案。
user347187

虽然我也借助来解决了问题view.recycler_view.post,但我还是使用了notifyItemInserted。就我而言,它已经是UI线程了。
CoolMind

6

当用户滚动适配器时清除适配器中的列表(使项目持有者的位置发生更改),ui上的列表和项目之间的引用丢失,在下一个“ notifyDataSetChanged”请求中发生错误时,将发生此错误 。

固定:

查看您的更新列表方法。如果你做类似的事情

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

===> Error occur

怎么修。创建新的列表对象以进行缓冲区处理,然后再次分配给主列表

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

感谢Nhan Cao的大力帮助:)


4

在修改Adapter实现以使用items数组的副本而不是引用之后,我的问题消失了。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);
}

这样可以解决问题,但是会不会占用原来内存的两倍?
Sreekanth Karumanaghat

@ MiguelA.Gabriel这会影响性能吗?例如,在我的情况下,我过于频繁地更新recylerview的数组,所以目前我正在这样做suggestionsRecyclerView.swapAdapter(new CandidatesAdapter(mSuggestions), true); ,这是我的构造函数 public CandidatesAdapter(List<String> suggestionsList) { this.suggestionsList = new ArrayList<>(suggestionsList); }
Mateen Chaudhry

@ mateen-chaudhry可能会。您需要根据自己的情况进行测试并做出决定,或者尝试使用其他建议的解决方案。正如我所说的,这只是一种解决方法,对我而言对我来说是有效的。
米格尔·加布里埃尔

3

我也遇到过同样的情况。在清除收藏集之前,通过添加代码解决了该问题。

mRecyclerView.getRecycledViewPool().clear();


3

就我而言,我正在更新项目并notifyDataSetChanged在非UI线程中调用。在大多数情况下,它都有效,但是当许多更改迅速发生时,它就会崩溃。当我这样做的时候,基本上

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
是的,同样的问题。您只给出原因。.如何解决?
兰吉思·库玛

@RanjithKumar,请分享您解决上述问题的方式。我使用mRecyclerView.getRecycledViewPool()。clear();解决了它 在notifyDataSetChanged之前,并在适配器的更新功能周围使用同步块
Attiq ur Rehman

可以请你看看我的代码,我想我的问题是,像你这样的,你能不能帮我stackoverflow.com/questions/50213362/...
MATEEN乔杜里


2

为解决此问题,只需在更新回收视图之前用空列表调用notifyDataSetChanged()即可。

例如

//Method for refresh recycle view

    if (!hcpArray.isEmpty())

hcpArray.clear(); //更新回收视图列表

adapter.notifyDataSetChanged();

2
没办法。
Miha_x64

@Milha我没有其他解决崩溃问题的方法。但是上面的解决方案对我有用。如果不是解决方案,请告诉我正确的解决方法。
EKN

这取决于。您可以尝试使用DiffUtil(一种用于更新RecyclerView内容的通用工具)。
Miha_x64

2

就我而言,我只是删除了 setHasStableIds(true);


但是HasStableIds(true)可以提高Rv的性能,是否有其他解决方案?
Sreekanth Karumanaghat

实际上,我认为这可能是由于不同的原因造成的,因此,基于根本原因,可能对此问题有不同的解决方案。
Sreekanth Karumanaghat

2

在我的情况下,我试图在后台线程上更改适配器的内容,但是在主/ ui线程上调用了notify *。

这是不可能的!之所以将notify强制到主线程,是因为recyclerview希望您在主线程上甚至在同一调用堆栈上编辑后备适配器。

要解决该问题,请确保在ui /主线程上进行对适配器的每个操作以及每个notify ...调用!


2
将项目添加到适配器的列表中应该在后台线程上完成,并在postexecute上调用notify。如果添加许多数据,则在ui线程中添加数据会使应用程序冻结几毫秒或几秒钟
dione llorera 18/09/1

与@dionellorera达成一致,应该明确指出,“适配器内容的更改”明确意味着直接修改任何数据,无论是原始值,对象的属性还是对象本身
OzzyTheGiant

2

我最近在使用新的Android体系结构组件时遇到了这种令人讨厌的堆栈跟踪。本质上,我有一个使用LiveData在Fragment中观察到的ViewModel中的项目列表。当ViewModel为数据发布新值时,片段将更新适配器,传入这些新的数据元素并通知适配器已发生更改。

不幸的是,当将新的数据元素传递给适配器时,我无法说明ViewModel和Adapter都指向同一对象引用这一事实!意思是如果我更新数据并调用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->此列表是您在adapter中使用的列表。


2

对我来说,在添加以下代码行后,它起作用了:

mRecyclerView.setItemAnimator(null);

2
在大多数情况下,这不是解决方法,如果您想动画,则需要重写适配器代码并发现通知更改的错误
Dragos Rachieru

它对我来说很好用。我正在使用真正的适配器,所以我无法控制流量,并且我以某种导致此问题的样式启用了windowActivityTransitions,谢谢您节省我的时间。
Arul Mani

1

尝试清除列表时可能会发生此问题,如果要清除数据列表,尤其是在使用pull刷新时,请尝试使用布尔值标志,将其初始化为false,并在OnRefresh方法内将其设为true,然后清除dataList如果flag在添加新数据之前为true,然后将其设置为false。

您的代码可能像这样

 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

我遇到了类似的问题,只是想通了。我为一个测试案例硬编码了一些示例,但是并不能确保它们每个都返回唯一的ID,这对我来说导致以下崩溃。修复ID可解决此问题,希望这对其他人有所帮助!


1

我也有错误:

原因:我试图从Async任务更新Recycler View,同时尝试获取旧的已删除viewHolders。

代码:按一下按钮即可生成数据,逻辑如下

  1. 清除回收者视图中的最后一个项目
  2. 调用异步任务以生成数据
  3. OnPostExecute更新回收者视图和NotifyDataSetChanged

问题:每当我快速滚动之前就生成数据

检测到不一致。无效的视图持有器适配器positionViewHolder java.lang.IndexOutOfBoundsException:检测到不一致。无效的项目位置20(偏移量:2)。状态:3

解决方案:我不保留在生成我的数据之前清除RecyclerView的方法,而是保留它,然后将其替换为新数据,调用NotifyDatasetChanged,如下所示;

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

你能看看我的代码吗,我认为我的问题就像你的[link](stackoverflow.com/questions/50213362/…
Mateen Chaudhry

1

通知之前,只需删除布局管理器的所有视图即可。喜欢:

myLayoutmanager.removeAllViews();

有用。我在滚动加载和制表符更改时遇到问题。
Warwicky

1

ListAdapter (androidx.recyclerview.widget.ListAdapter)致电adapter.submitList(null)前使用通话adapter.submitList(list)

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

0

我发现设置mRecycler.setLayoutFrozen(true); 在swipeContainer的onRefresh方法中。

为我解决了问题。

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

        }
    });

0

这是一个令人讨厌的错误。

为了处理我的项目单击,我使用了RecyclerView.OnItemTouchListener本问题中找到的解决方案类似的实现。

经过多次刷新RecyclerView的数据源并单击一个项目之后,这IndexOutOfBoundsException会使我的应用程序崩溃。单击某个项目后,RecyclerView内部人员将继续寻找正确的基础视图并返回其位置。检查出的源代码,我看到有一些TasksThreads调度。简而言之,基本上只是两个数据源相互混合而不同步的非法状态,整个过程变得疯狂。

基于此,我删除了对的实现,RecyclerView.OnItemTouchListener只是点击ViewHolderAdapter我自己的:

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

}

这可能不是最好的解决方案,但暂时不会崩溃。.希望这可以节省您一些时间:)。


每次调用onBind时创建一个新对象将导致大量对象被垃圾回收,并且用户可能会遇到冻结。
dephinera

0

Lint给了我有关不一致的建议:我写了(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进行完整说明!!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.