RecyclerView crashes when “scrapped or attached views may not be recycled”

前端 未结 27 2627
灰色年华
灰色年华 2020-11-29 19:50

I\'m using a simple implementation of RecyclerView taken from the Android website using a StaggeredGridLayoutManager and I keep getting this error

相关标签:
27条回答
  • 2020-11-29 20:12

    I removed the android:animateLayoutChanges from layout property and problem has been resolved.

    0 讨论(0)
  • 2020-11-29 20:12

    I saw this happen for me when I used a custom object in the ViewHolder for the RecyclerView adapter.

    To fix the issue I cleared the custom object which in my case was a timer in the onViewRecycled(ViewHolder holder) for the adapter as below:

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

    This fixed the bug.

    0 讨论(0)
  • 2020-11-29 20:12
        /**
         * Informs the recycler whether this item can be recycled. Views which are not
         * recyclable will not be reused for other items until setIsRecyclable() is
         * later set to true. Calls to setIsRecyclable() should always be paired (one
         * call to setIsRecyclabe(false) should always be matched with a later call to
         * setIsRecyclable(true)). Pairs of calls may be nested, as the state is internally
         * reference-counted.
         *
         * @param recyclable Whether this item is available to be recycled. Default value
         * is true.
         *
         * @see #isRecyclable()
         */
        public final void setIsRecyclable(boolean recyclable) {
            mIsRecyclableCount = recyclable ? mIsRecyclableCount - 1 : mIsRecyclableCount + 1;
            if (mIsRecyclableCount < 0) {
                mIsRecyclableCount = 0;
                if (DEBUG) {
                    throw new RuntimeException("isRecyclable decremented below 0: " +
                            "unmatched pair of setIsRecyable() calls for " + this);
                }
                Log.e(VIEW_LOG_TAG, "isRecyclable decremented below 0: " +
                        "unmatched pair of setIsRecyable() calls for " + this);
            } else if (!recyclable && mIsRecyclableCount == 1) {
                mFlags |= FLAG_NOT_RECYCLABLE;
            } else if (recyclable && mIsRecyclableCount == 0) {
                mFl`enter code here`ags &= ~FLAG_NOT_RECYCLABLE;
            }
            if (DEBUG) {
                Log.d(TAG, "setIsRecyclable val:" + recyclable + ":" + this);
            }
        }
    
    0 讨论(0)
  • 2020-11-29 20:13

    In my case the problem was because of the incorrect implementing of this method public long getItemId(int position) (overrided from RecyclerView.Adapter method).

    The old code will get two different ids for the same item (in my case it is the footer item), after fixing the implementation the issue has gone.

    0 讨论(0)
  • 2020-11-29 20:13

    A Peculiar case which occured for me was that i had a view member in the adapter and i was lazy instantiating a view which there is no need to do with the recycle view.

    It also goes against the recycle views principles which as your storing a reference to the view in this case. I give a quick example below:

    // typically we would do this in a grid view adapter:
    View v;
    // ...
    if(v = null){
    v = LayoutInflater.inflate ...;
    }
    
    // Now with recycle view there is NO need to store a reference to View
    // and lazy instantiate. So get rid of your View v member
    
    0 讨论(0)
  • 2020-11-29 20:15

    It took me two days but could not get around this, in the end, I had to disable the item prefetch.

    When setting the layout manager you can simply call

    mGridLayoutManager.setItemPrefetchEnabled(false);

    It made the error go away for me. Hope it will be useful for someone.

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