2024/04/19 共 6705 字,约 20 分钟

异常一

参考网页

异常堆栈信息

06-27 16:49:50.463 E/AndroidRuntime(20889): FATAL EXCEPTION: main   
06-27 16:49:50.463 E/AndroidRuntime(20889): Process: a, PID: 20889   
06-27 16:49:50.463 E/AndroidRuntime(20889): java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.RecyclerView.assertNotInLayoutOrScroll(RecyclerView.java:2349)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.RecyclerView$RecyclerViewDataObserver.onChanged(RecyclerView.java:4551)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.RecyclerView$AdapterDataObservable.notifyChanged(RecyclerView.java:10366)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.RecyclerView$Adapter.notifyDataSetChanged(RecyclerView.java:6044)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at a.gui.adapters.TrackAdapters.QueueTrackAdapter$TrackViewHolder.onItemClear(QueueTrackAdapter.java:522)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at a.gui.adapters.swipedrag.SimpleItemTouchHelperCallback.clearView(SimpleItemTouchHelperCallback.java:124)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.helper.ItemTouchHelper.onChildViewDetachedFromWindow(ItemTouchHelper.java:876)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.RecyclerView.dispatchChildDetached(RecyclerView.java:6234)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.RecyclerView.access$1200(RecyclerView.java:151)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.RecyclerView$5.removeViewAt(RecyclerView.java:651)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.ChildHelper.removeViewAt(ChildHelper.java:168)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.RecyclerView$LayoutManager.removeViewAt(RecyclerView.java:7092)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.RecyclerView$LayoutManager.scrapOrRecycleView(RecyclerView.java:7638)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.RecyclerView$LayoutManager.detachAndScrapAttachedViews(RecyclerView.java:7624)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:546)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at a.gui.activities.QueueActivity$WrapContentLinearLayoutManager.onLayoutChildren(QueueActivity.java:359)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3260)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3069)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1478)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.java:1542)   
06-27 16:49:50.463 E/AndroidRuntime(20889): at android.support.v7.widget.RecyclerView.onTouchEvent(RecyclerView.java:2649)   
......   
......   
06-27 16:49:50.464 E/AndroidRuntime(20889): at android.os.Handler.handleCallback(Handler.java:836)   
06-27 16:49:50.464 E/AndroidRuntime(20889): at android.os.Handler.dispatchMessage(Handler.java:103)   
06-27 16:49:50.464 E/AndroidRuntime(20889): at android.os.Looper.loop(Looper.java:203)   
06-27 16:49:50.464 E/AndroidRuntime(20889): at android.app.ActivityThread.main(ActivityThread.java:6347)   
06-27 16:49:50.464 E/AndroidRuntime(20889): at java.lang.reflect.Method.invoke(Native Method)   
06-27 16:49:50.464 E/AndroidRuntime(20889): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)   
06-27 16:49:50.464 E/AndroidRuntime(20889): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)  

如何复现

左滑或右滑删除Item的时候,调用了notifyDataSetChanged来刷新数据源。

如何解决

简书的文章中将notifyDataSetChanged();方法的调用放到Handler中,问题得到解决。

问题(FIXME)

为什么在ListView中不会出现这个问题?
RecyclerView抛出这个异常是为了避免什么?

异常二

参考网页

异常堆栈信息

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 6(offset:6).  
        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3300)  
        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3258)  
        at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1803)  
        at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1302)  
        at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1265)  
        at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1093)  
        at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:956)  
        at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:2715)  
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)  
        at android.view.Choreographer.doCallbacks(Choreographer.java:555)  
        at android.view.Choreographer.doFrame(Choreographer.java:524)  
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)  
        at android.os.Handler.handleCallback(Handler.java:615)  
        at android.os.Handler.dispatchMessage(Handler.java:92)  
        at android.os.Looper.loop(Looper.java:137)  
        at android.app.ActivityThread.main(ActivityThread.java:4921)  
        at java.lang.reflect.Method.invokeNative(Native Method)  
        at java.lang.reflect.Method.invoke(Method.java:511)  
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)  
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)  
        at dalvik.system.NativeStart.main(Native Method)  

如何复现

我看两篇文章也没有太搞清楚异常是为什么报出来的,大概就是添加或者删除item的时候导致的不一致,致使内部报错。

如何解决

复写一个WrapLayoutManager捕获异常

public class WrapContentLinearLayoutManager extends LinearLayoutManager {  
    public WrapContentLinearLayoutManager(Context context) {  
        super(context);  
    }  
  
    public WrapContentLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {  
        super(context, orientation, reverseLayout);  
    }  
  
    public WrapContentLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {  
        super(context, attrs, defStyleAttr, defStyleRes);  
    }  
  
    @Override  
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {  
        try {  
            super.onLayoutChildren(recycler, state);  
        } catch (IndexOutOfBoundsException e) {  
            e.printStackTrace();  
        }  
    }  
}  

调用

mRecyclerView.setLayoutManager(new WrapContentLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));  

问题(FIXME)

  • 为什么ListView没有出现这个问题?
  • 我自己的项目中,adapter和外部操作的是同一个ArrayList,还是会报错,为什么RecyclerView会这样处理,出现明显的错误,难道有其他的调用方式?
  • 我甚至在一个网页上看到有人说RecyclerView每隔1s更新一下任务太繁重了?手机的处理应该是毫秒级的,何来繁重?

文档信息

Search

    Table of Contents