android studio 报错日志:
09-22 11:15:16.433 31234-31234/com.fssmw.pm E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.xxx.pm, PID: 31234
java.lang.IllegalArgumentException: Scrapped or attached views may not be recycled. isScrap:false isAttached:true
at android.support.v7.widget.RecyclerView$Recycler.recycleViewHolderInternal(RecyclerView.java:5736)
at android.support.v7.widget.RecyclerView$Recycler.quickRecycleScrapView(RecyclerView.java:5843)
at android.support.v7.widget.RecyclerView$LayoutManager.removeAndRecycleScrapInt(RecyclerView.java:8501)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep3(RecyclerView.java:3656)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3323)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3844)
at android.view.View.layout(View.java:17194)
at android.view.ViewGroup.layout(ViewGroup.java:5579)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1189)
at android.view.View.layout(View.java:17194)
at android.view.ViewGroup.layout(ViewGroup.java:5579)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:396)
at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
at android.view.View.layout(View.java:17194)
at android.view.ViewGroup.layout(ViewGroup.java:5579)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:396)
at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
at android.view.View.layout(View.java:17194)
at android.view.ViewGroup.layout(ViewGroup.java:5579)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:396)
at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
at android.view.View.layout(View.java:17194)
at android.view.ViewGroup.layout(ViewGroup.java:5579)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:2001)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1844)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1753)
at android.view.View.layout(View.java:17194)
at android.view.ViewGroup.layout(ViewGroup.java:5579)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:396)
at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
at android.view.View.layout(View.java:17194)
at android.view.ViewGroup.layout(ViewGroup.java:5579)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:2001)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1844)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1753)
at android.view.View.layout(View.java:17194)
at android.view.ViewGroup.layout(ViewGroup.java:5579)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:396)
at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
at com.android.internal.policy.PhoneWindow$DecorView.onLayout(PhoneWindow.java:2768)
at android.view.View.layout(View.java:17194)
at android.view.ViewGroup.layout(ViewGroup.java:5579)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2623)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2276)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1338)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6872)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:899)
at android.view.Choreographer.doCallbacks(Choreographer.java:701)
at android.view.Choreographer.doFrame(Choreographer.java:636)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:885)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5966)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:749)
解决方案:
网上给出的方案大致如下:
1.设置recycleview 的android:animateLayoutChanges为false
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
//默认是true改为false
android:animateLayoutChanges="false">
</android.support.v7.widget.RecyclerView>
2.iem中获取焦点的控件(如EditTex)使之无法销毁,使其父布局优先获取焦点
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/el_root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
<!-- 优于item获取焦点-->
android:focusable="true"
android:focusableInTouchMode="true"
>
<RelativeLayout
android:id="@+id/ll_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:paddingBottom="@dimen/dp_6"
android:paddingLeft="@dimen/dp_15"
android:paddingRight="@dimen/dp_15"
android:paddingTop="@dimen/dp_6">
<EditText
android:id="@+id/et_search_foreman"
style="@style/text_normal_light"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/dp_6"
android:background="@drawable/bg_et_gray"
android:drawableLeft="@mipmap/ic_search"
android:drawablePadding="@dimen/dp_6"
android:hint="搜索"
android:imeOptions="actionSearch"
android:inputType="text"
android:maxLines="1"
android:paddingBottom="@dimen/dp_8"
android:paddingLeft="@dimen/dp_20"
android:paddingRight="@dimen/dp_26"
android:paddingTop="@dimen/dp_8"
/>
<ImageView
android:id="@+id/img_clean"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="@dimen/dp_15"
android:layout_marginTop="18dp"
android:src="@mipmap/ic_clean"
android:visibility="gone"/>
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/xrcl_invite_foreman"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/ll_search"
>
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
3.真正原因,是在recycleview的数据源集合发生变化时,adapter没有及时刷新(notifyDataSetChanged)导致。
//加载服务器数据方法
private void loadNetData(final int flag) {
searchParam = isSearch ? etSearchForeman.getText().toString().trim() : "";
pageIndex = (flag == 1) ? pageIndex + 1 : 1;
presenter.request(new Service() {
@Override
public Observable<DTO<List<POInviteForeman>>> dispatcher() {
return presenter.mOrderService.foremanlist(new BOInviteForeman(pageIndex, pageSize, mPprofessionid, searchParam));
}
}, new Return() {
@Override
public void onSuccess(DTO po) {
//服务器数据接口请求成功回调方法
//flag==1 加载更多
if (0 == flag) {
//dataList为recycleview数据源
dataList.clear();
}
dataList.addAll((List<POInviteForeman>) po.getData());
//refresh 里面调用了notifyDataSetChanged()
mAdapter.refresh(dataList);
xrclInviteForeman.loadMoreComplete();
}
});
}
以上代码段中“dataList.clear();”是在服务器接口请求成功后执行,如果在 presenter.request()之前执行,“ mAdapter.refresh(dataList);”还在onSuccess(DTO po)中,此时如果一些原因onSuccess(DTO po) 中代码没有执行,就会出现次错误。