Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android RecyclerView在以下情况下崩溃;废弃或附加的视图不得回收。”;_Android_Android Recyclerview - Fatal编程技术网

Android RecyclerView在以下情况下崩溃;废弃或附加的视图不得回收。”;

Android RecyclerView在以下情况下崩溃;废弃或附加的视图不得回收。”;,android,android-recyclerview,Android,Android Recyclerview,我使用的是一个简单的RecyclerView实现,该实现来自Android网站,使用的是StaggedGridLayoutManager,我不断收到这个错误,导致我的应用程序崩溃: java.lang.IllegalArgumentException: Scrapped or attached views may not be recycled. isScrap:false isAttached:true at android.support.v7.widget.Recy

我使用的是一个简单的
RecyclerView实现,该实现来自Android网站,使用的是
StaggedGridLayoutManager
,我不断收到这个错误,导致我的应用程序崩溃:

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:3501)
            at android.support.v7.widget.RecyclerView$LayoutManager.scrapOrRecycleView(RecyclerView.java:5355)
            at android.support.v7.widget.RecyclerView$LayoutManager.detachAndScrapAttachedViews(RecyclerView.java:5340)
            at android.support.v7.widget.StaggeredGridLayoutManager.onLayoutChildren(StaggeredGridLayoutManager.java:572)
            at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:1918)
            at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2155)
            at android.view.View.layout(View.java:14008)
            at android.view.ViewGroup.layout(ViewGroup.java:4373)
            at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1021)
            at android.view.View.layout(View.java:14008)
            at android.view.ViewGroup.layout(ViewGroup.java:4373)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
            at android.view.View.layout(View.java:14008)
            at android.view.ViewGroup.layout(ViewGroup.java:4373)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
            at android.view.View.layout(View.java:14008)
            at android.view.ViewGroup.layout(ViewGroup.java:4373)
            at android.support.v7.internal.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:502)
            at android.view.View.layout(View.java:14008)
            at android.view.ViewGroup.layout(ViewGroup.java:4373)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
            at android.view.View.layout(View.java:14008)
            at android.view.ViewGroup.layout(ViewGroup.java:4373)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1663)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1521)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
            at android.view.View.layout(View.java:14008)
            at android.view.ViewGroup.layout(ViewGroup.java:4373)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
            at android.view.View.layout(View.java:14008)
            at android.view.ViewGroup.layout(ViewGroup.java:4373)
            at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1892)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1711)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:989)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4351)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
            at android.view.Choreographer.doCallbacks(Choreographer.java:562)
            at android.view.Choreographer.doFrame(Choreographer.java:532)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
            at android.os.Handler.handleCallback(Handler.java:725)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5041)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
            at dalvik.system.NativeStart.main(Native Method)  
简单地说,我的意思是它是从同一个实现中获得的,唯一的区别是我的网格项的布局是一个
ImageView
和两个
TextView
s,所以我不会麻烦重新发布我的代码


还有谁知道如何处理这个错误吗?

如果XML中的
android:animateLayoutChanges
设置为true,并且在Java代码中调用RecyclerView的适配器上的
notifyDataSetChanged()
,就会导致这个错误


因此,请避免在RecyclerViews中使用android:animateLayoutChanges

我也必须处理此崩溃,在我的情况下,它与
android:animateLayoutChanges
无关

我们正在构建的
RecyclerView
中有多种类型的视图,有些视图中有
EditText
s。过了一段时间,我们把这个问题归结为与焦点相关。此错误发生在回收
EditText
s时,其中一个错误已被关注


当然,当新数据绑定到回收视图时,我们尝试清除焦点,但直到
android:focusableInTouchMode=“true”
设置为
RecycleView
时,这才起作用。实际上,这是最终解决此问题所需的唯一更改。

发生在我身上的一个特殊情况是,我在适配器中有一个视图成员,我懒得实例化一个视图,而不需要使用循环视图

这也违反了循环视图原则,在本例中,循环视图原则是存储对视图的引用。下面我举一个简单的例子:

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

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

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

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

这修复了这个错误。

在使用slimfit sticky Header时,我遇到了这个错误。这是由于设置错误的第一个位置造成的。我得到了答案


只需确保您为mSectionFirstPosition传递了正确的值

我从layout属性中删除了
android:animateLayoutChanges
,问题已经解决。

我使用
com.squareup.picasso.RequestCreator

public void into(android.widget.ImageView target,
             Callback callback)
从Internet下载图片后动态调整ImageView的大小,并保存已调整大小的宽度和高度以保留视图大小。我之所以出现此异常,是因为我将
LayoutParams
保存在
Map
中,并在onBindViewHolder中检索它并直接将其设置为我的
ImageView
。我通过使用
ImmutablePair
来修复这个问题,只存储ImageView的大小,而不是许多其他状态,并使用下面的代码来恢复它

ViewGroup.LayoutParams params = image.getLayoutParams();
params.width = widthAndHeight.getLeft();
params.height = widthAndHeight.getRight();
image.setLayoutParams(params);

请允许我为此类问题添加另一个可能的解决方案。我在
RecyclerView
中遇到了与库中粘性标题相同的问题。我使用
MatrixCursor
将数据设置为
recycleServiceWCursorAdapter
。出现此问题的原因是,对于所有标题,ID列等于
0
。希望这能帮助某人节省几天的调试时间。

对于我来说,在更高级别的视图组上进行LayoutTransition会导致相同的错误。

我今天早上遇到了这个问题,但我面临的原因与上面提到的不同

通过调试,我发现我的ViewHolder中的项目视图具有
mParent
,并且它不是空的,在正常情况下它应该是空的(这就是日志所说的“附加视图可能无法回收”,我认为这意味着如果子视图已经附加到父视图,那么在回收时会导致失败。)

但我并不是每次都手动附加子视图。我发现这是在我尝试在我的ViewHolder中膨胀子视图时完成的,类似于:

layoutInflater.inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)
最后一个参数
attachToRoot
应该为false

在我将其更改为
false
后,我修复了我的问题

顺便说一句,我只在将我的支持库升级到最新版本25.0.0时看到此崩溃。在我使用版本23.4.0之前,我没有看到这个问题发生。我想在最新的支持库中应该有一些更改


希望有帮助。

我通过删除
onCreateViewHolder中的
parent.addView()
解决了这个问题

这是我的密码

public MyViewHolder onCreateViewwHolder(ViewGroup parent, int viewType)  {
    Button addButton = new Button(context);
    //parent.addView(addButton);
    return new MyViewHolder(addButton);
}
函数位于
android.support.v7.widget.RecycleServiceWrecycler.RecycleServiceWholderInternal()
检查我的按钮是否已有父按钮。如果我们将按钮添加到父级,它也将被分配给它的
mParent
变量。

/**
    /**
     * 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);
        }
    }
*通知回收商此项目是否可以回收。不是 *在设置setIsRecyclable()之前,不会将可回收物重新用于其他项目 *后来设置为true。对setIsRecyclable()的调用应始终成对(一个) *对SetIsRecyCabe的调用(false)应始终与以后对的调用相匹配 *setIsRecyclable(true))。调用对可以嵌套,因为状态是内部的 *参考计数。 * *@param recyclable此项目是否可回收。默认值 *这是真的。 * *@see#isRecyclable() */ 公共最终作废集可回收(布尔可回收){ 可回收错误计数=可回收?可回收错误计数-1:可回收错误计数+1; 如果(误回收计数<0){ 可回收错误计数=0; 如果(调试){ 抛出新的运行时异常(“isRecyclable递减到0以下:”+ “无与伦比的一对刚毛
    /**
     * 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);
        }
    }
setHasStableIds(true);
@Override
public long getItemId(int position) {
    return position;
}
View itemView = mRecyclerView.getLayoutManager().findViewByPosition(position);
if (itemView != null && itemView.getParent() != null) {
    ((ViewGroup) itemView.getParent()).removeView(itemView);
}
notifyItemRemoved(position);
    nameLP = new LinearLayout.LayoutParams(context.getResources().getDisplayMetrics().widthPixels, LinearLayout.LayoutParams.WRAP_CONTENT);
    nameLP2 = new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT);
Transition.excludeChildren(yourRecyclerView, true)
Transition.excludeTarget(yourRecyclerView, true)