QA提Bug说某个列表上下滑动会崩溃(非必现)。哎…,最怕的就是这种难以复现的问题了。
问题产生的原因是使用了support-v7 的RecyclerView,在刷新数据的时候会出现以下异常:
java.lang.NullPointerException
at com.rcplatform.livechat.im.SinchIMService$b.a(SinchIMService.java:592)
at com.rcplatform.livechat.ui.MainActivity.a(MainActivity.java:794)
at com.rcplatform.livechat.ui.IMServiceActivity$1.onServiceConnected(IMServiceActivity.java:26)
at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1113)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1130)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5232)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:746)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
at dalvik.system.NativeStart.main(Native Method)
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{418cb040 position=10 id=-1, oldPos=-1, pLpos:-1 no parent}
at android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:4801)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4932)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4913)
at android.support.v7.widget.LinearLayoutManager$b.a(LinearLayoutManager.java:2029)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1414)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1377)
at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1193)
at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1043)
at android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.java:1552)
at android.support.v7.widget.RecyclerView.onTouchEvent(RecyclerView.java:2649)
at android.view.View.dispatchTouchEvent(View.java:7566)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2205)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1940)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2211)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1954)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2211)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1954)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2211)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1954)
at com.rcplatform.livechat.widgets.ItemVisiableViewPager.dispatchTouchEvent(ItemVisiableViewPager.java:52)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2211)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1954)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2211)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1954)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2211)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1954)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2211)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1954)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2211)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1954)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2211)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1954)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1973)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1425)
at android.app.Activity.dispatchTouchEvent(Activity.java:2424)
at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:67)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1921)
at android.view.View.dispatchPointerEvent(View.java:7746)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3899)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3794)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3389)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3439)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3408)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3493)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3416)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3550)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3389)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3439)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3408)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3416)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3389)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5436)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5416)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5387)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5510)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:182)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:132)
at android.os.Looper.loop(Looper.java:124)
at android.app.ActivityThread.main(ActivityThread.java:5232)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:746)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
at dalvik.system.NativeStart.main(Native Method)
从日志可以看到,这个崩溃发生在 底层。比较合适的办法是把LinearLayoutManager的onLayoutChildren方法的异常捕获。
1、创建一个类LinearLayoutManagerWrapper继承LinearLayoutManager,重写onLayoutChildren方法
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();
}
}
}
然后设置RecyclerView的LayoutManager:
recyclerView.setLayoutManager(new WrapContentLinearLayoutManager(getContext()));