带有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

查看:395
本文介绍了带有RecyclerView的片段:java.lang.IllegalArgumentException:废弃或附加的视图可能无法回收。 isScrap:false isAttached:true的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不断收到 java.lang.IllegalArgumentException:废弃或附加的视图可能无法回收。 isScrap:false isAttached:true 在使用Fragment和RecyclerView时。
我只有1个Activity在多个片段之间切换。在活动的onCreate上,我设置了默认片段,恰好在文档中实现了RecyclerView。在活动启动时,我获取java.lang.IllegalArgumentException:废弃或附加的视图可能无法回收。 isScrap:false isAttached:true



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



任何帮助表示赞赏。



谢谢

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



活动的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);
}
//初始化组件
initActionBar(checkedSideMenuItemLabel,savedInstanceState);
initSideMenuArrayAdapter();
initSideMenu(checkedSideMenuItemLabel,savedInstanceState);
initActionBarDrawerToggle();
fragmentManager = this.getSupportFragmentManager();
if(savedInstanceState == null){
//在创建活动时设置默认片段。
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
DashboardFragment df = new DashboardFragment();
fragmentTransaction.replace(R.id.fragment_container,df,DashboardFragment.class.toString());
fragmentTransaction.commit();




片段的onResume()

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

片段布局 $ b

 <?xml version =1.0encoding =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 / myRecyclerViewstyle =@ style / Main_Content_List_View/>
< / LinearLayout>

活动布局

 <?xml version =1.0encoding =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>

<! - 操作栏工具栏 - >
< 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_parentandroid:layout_height =fill_parent
android:id =@ + id / fragment_containerandroid:orientation =vertical>

< / LinearLayout>

< include layout =@ layout / side_menu_layout/>


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

< / LinearLayout>

RecyclerView商品布局

 <?xml version =1.0encoding =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。



希望这有助于其他人需要..



谢谢

I keep getting java.lang.IllegalArgumentException: Scrapped or attached views may not be recycled. isScrap:false isAttached:true when using Fragment with RecyclerView. I have only 1 Activity which switches between multiple fragments. On activity's onCreate I set the default fragment which happens to have a RecyclerView implemented exactly like in documentation. Upon activity startup I get java.lang.IllegalArgumentException: Scrapped or attached views may not be recycled. isScrap:false isAttached:true .

The problem is if I load at the beginning an empty fragment container and afterwards navigate to the fragment with RecyclerView, it works fine. Also I don't use android:animateLayoutChanges or notifyDataSetChanged() like stated here Currently I setup the RecyclerView in onResume() method of the Fragment. I've tried switching it to other lifecycle methods but not luck.

Any help is appreciated.

Thanks

I have added only relevant code snippets. I believe that is somehow lifecycle related, giving the fact that it works if I don't set the fragment in onCreate() of the Activity. It worked when I had a ListView instead of RecyclerView. I did not post the code for RecyclerView because it is the same as in documentation.

Activity's 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's onResume()

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

Fragment layout

    <?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's layout

<?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 item layout

<?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>

解决方案

Ok so I've found were the problem was. In my ViewHolder I had in addition to the layout Views, an ORMlite entity (could've been any object that was not part of the layout). The problem was that the ViewHolder's equals() and hashcode() methods were based on the entity which was null. The reason it was null was because with RecyclerView you don't have access to the data position in onCreateViewHolder(), but only in onBindViewHolder(). The adapter data is a list of ORMlite entities in my case, and I want to bundle the entity inside the holder. (Still have to find a way to do this...)

I was expecting a NullPointerException in this case. I've manage to get a NullPointerException by calling holder.setIsRecyclable(true).

Hope this helps others in need..

Thanks

这篇关于带有RecyclerView的片段:java.lang.IllegalArgumentException:废弃或附加的视图可能无法回收。 isScrap:false isAttached:true的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆