Cannot change whether this adapter has stable IDs while the adapter has registered observers

后端 未结 4 1415
难免孤独
难免孤独 2020-12-17 09:06

I am using RecyclerView in my android project and its performance has been really awful. From the answers here, I tried adding adapter.setHasStableIds(true); to

相关标签:
4条回答
  • 2020-12-17 09:09

    You can not use adapter.setHasStableIds(true); with ObservableArrayList/ObservableFields

    0 讨论(0)
  • 2020-12-17 09:10

    You must set the adapter's hasStableIds to true BEFORE you assign the adapter to your recyclerview.

    YourAdapter adapter = new YourAdapter();
    adapter.setHasStableIds(true);
    myRecyclerView.setAdapter(adapter);
    
    0 讨论(0)
  • 2020-12-17 09:18

    as the recyclerView source code:

        /**
         * Indicates whether each item in the data set can be represented with a unique identifier
         * of type {@link java.lang.Long}.
         *
         * @param hasStableIds Whether items in data set have unique identifiers or not.
         * @see #hasStableIds()
         * @see #getItemId(int)
         */
        public void setHasStableIds(boolean hasStableIds) {
            if (hasObservers()) {
                throw new IllegalStateException("Cannot change whether this adapter has "
                        + "stable IDs while the adapter has registered observers.");
            }
            mHasStableIds = hasStableIds;
        } .   
    

    so you can workaround it .

        if (!adapter.hasObservers()) {
            adapter.setHasStableIds(true)
        }     
    
    0 讨论(0)
  • 2020-12-17 09:22

    In my case, it's because the I put the setHasStableIds(true) inside the Fragment's onActivityCreated(). The Fragment is the main point of my application so it never gets popped from back stack.

    class LocalFragment: Fragment() {
        private val adapter = LocalAdapter()
     
        override fun onActivityCreated(savedInstanceState: Bundle?) {
            adapter.setHasStableIds(true)
        }
    }
    

    The problem here is that the onActivityCreated() is called every time the Fragment is navigated to. However, as the Fragment is still alive in the back stack, the private val adapter field is still the same object that had its setStableIds(true) called previously.

    class LocalFragment: Fragment() {
        private var adapter = LocalAdapter()
     
        override fun onActivityCreated(savedInstanceState: Bundle?) {
            adapter = LocalAdapter() // Re-assign the adapter
            adapter.setHasStableIds(true)
        }
    }
    

    Solution is to reassign the RecyclerView.Adapter object every time the fragment is switched to.

    0 讨论(0)
提交回复
热议问题