带有 RecyclerView 的片段:java.lang.IllegalArgumentException:报废或附加的视图可能不会被回收。 isScrap:false isAttached:true

Fragment with RecyclerView : java.lang.IllegalArgumentException: Scrapped or attached views may not be recycled. isScrap:false isAttached:true

我不断收到 java.lang.IllegalArgumentException:废弃或附加的视图可能无法回收。 isScrap:false isAttached:true 当 Fragment 与 RecyclerView 一起使用时。 我只有 1 个 Activity 在多个片段之间切换。在 activity 的 onCreate 上,我设置了默认片段,它恰好有一个 RecyclerView 实现,就像在文档中一样。在 activity 启动时,我 得到 java.lang.IllegalArgumentException:废弃或附加的视图可能不会被回收。 isScrap:false isAttached:true

问题是,如果我在开始时加载一个空的片段容器,然后使用 RecyclerView 导航到片段,它工作正常。 我也不使用 android:animateLayoutChangesnotifyDataSetChanged()here 目前我在片段的 onResume() 方法中设置了 RecyclerView。我试过将它切换到其他生命周期方法,但运气不好。

感谢任何帮助。

谢谢

我只添加了相关的代码片段。我相信这在某种程度上与生命周期相关,如果我不在 Activity 的 onCreate() 中设置片段,它就会起作用。当我有一个 ListView 而不是 RecyclerView 时它起作用了。 我没有 post RecyclerView 的代码,因为它与文档中的代码相同。

Activity的onCreate

 public void onCreate(Bundle savedInstanceState) {
        Log.d(TAG,"### onCreate ###");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.efficientix_activity_layout);
        if(savedInstanceState != null){
            checkedSideMenuItemLabel = savedInstanceState.getInt("checkedSideMenuItemLabel");
        }
        //Init components
        initActionBar(checkedSideMenuItemLabel,savedInstanceState);
        initSideMenuArrayAdapter();
        initSideMenu(checkedSideMenuItemLabel,savedInstanceState);
        initActionBarDrawerToggle();
        fragmentManager = this.getSupportFragmentManager();
        if(savedInstanceState == null){
            //Set default fragment upon activity creation.
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            DashboardFragment df = new DashboardFragment();
            fragmentTransaction.replace(R.id.fragment_container,df,DashboardFragment.class.toString());
            fragmentTransaction.commit();
        }
    }

Fragment 的 onResume()

public void onResume() {
        super.onResume();
        if (recylerViewLayoutManager == null) {
            recylerViewLayoutManager = new LinearLayoutManager(this.getActivity());
        }
        recylerView.setLayoutManager(remindersLayoutManager);
        initRecylerViewAdapter();
        recylerView.setAdapter(recylerViewAdapter);
    }

片段布局

    <?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView android:id="@+id/myRecyclerView" style="@style/Main_Content_List_View"/>
</LinearLayout>

Activity的布局

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:efficientix="http://schemas.android.com/apk/res-auto"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <!-- The actionbar toolbar -->
    <include layout="@layout/actionbar_toolbar"/>

    <android.support.v4.widget.DrawerLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/menu_layout"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">

        <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent"
                      android:id="@+id/fragment_container" android:orientation="vertical">

        </LinearLayout>

        <include layout="@layout/side_menu_layout"/>


    </android.support.v4.widget.DrawerLayout>

</LinearLayout>

RecyclerView 项目布局

<?xml version="1.0" encoding="utf-8"?>
<android.widget.TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
                            style="@style/Main_Content_Table_Layout_List_Item">


    <TableRow style="@style/Main_Content_Table_Row_List_Item">
        <TextView android:id="@+id/description"
                  style="@style/Main_Content_TextView" />
        <ImageView android:id="@+id/category"
                  style="@style/Main_Content_ImageView"/>
    </TableRow>
    <TableRow style="@style/Main_Content_Table_Row_List_Item">
        <TextView android:id="@+id/alert_date"
                  style="@style/Main_Content_TextView" />
        <TextView android:id="@+id/type"
                  style="@style/Main_Content_TextView" />
    </TableRow>


</android.widget.TableLayout>

好的,我发现问题出在哪里。在我的 ViewHolder 中,除了布局视图之外,我还有一个 ORMlite 实体(可以是任何不属于布局的对象)。问题在于 ViewHolder 的 equals() 和 hashcode() 方法基于为 null 的实体。它为 null 的原因是因为使用 RecyclerView 您无法访问 onCreateViewHolder() 中的数据位置,而只能访问 onBindViewHolder() 中的数据位置。在我的例子中,适配器数据是一个 ORMlite 实体列表,我想将该实体捆绑在容器中。 (还是得想个办法。。。)

在这种情况下,我期待出现 NullPointerException。我设法通过调用 holder.setIsRecyclable(true).

获得了 NullPointerException

希望这对有需要的人有帮助..

谢谢

当我在 Recycler View 适配器的 ViewHolder 中使用自定义对象时,我看到了这种情况。

为了解决这个问题,我清除了自定义对象,在我的例子中,它是适配器的 onViewRecycled(ViewHolder holder) 中的一个计时器,如下所示:

public void onViewRecycled(ViewHolder holder) {
    if(holder instanceof  EntityViewHolder) {
        if(((EntityViewHolder)holder).timer != null) {
            ((EntityViewHolder) holder).timer.cancel();
        }
    }
    super.onViewRecycled(holder);
}

这修复了错误。