RecycleView中LayoutManager报is already attached to a RecyclerView的原因

213 阅读1分钟

原因

LayoutManager只能对应一个RecycleView,不能重复使用。

报错截图

image.png

源代码

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_example, container, false);

        mRecyclerView = (RecyclerView) view.findViewById(R.id.rv_test);
        Log.d(MainActivity.PRINT_LOG, "onCreateView: mRecyclerView:" + mRecyclerView + " --- " + mLayoutManager);
//        布局管理器
//        Log.d(MainActivity.PRINT_LOG, "onCreateView: mRecyclerView.getLayoutManager():" + mRecyclerView.getLayoutManager());
        if (mRecyclerView.getLayoutManager() == null) {
//            Log.d(MainActivity.PRINT_LOG, "onCreateView: mLayoutManager:" + mLayoutManager);
            
//            manager不能是单例
//            LinearLayoutManager manager = new LinearLayoutManager(getActivity());
            mRecyclerView.setLayoutManager(mLayoutManager);

        }
//        适配器
        mRecyclerView.setAdapter(exampleAdapter);

        return view;
    }

源码分析

RecycleView的setLayoutManager方法(第36行会进行绑定

public void setLayoutManager(@Nullable LayoutManager layout) {
    if (layout == mLayout) {
        return;
    }
    stopScroll();
    // TODO We should do this switch a dispatchLayout pass and animate children. There is a good
    // chance that LayoutManagers will re-use views.
    if (mLayout != null) {
        // end all running animations
        if (mItemAnimator != null) {
            mItemAnimator.endAnimations();
        }
        mLayout.removeAndRecycleAllViews(mRecycler);
        mLayout.removeAndRecycleScrapInt(mRecycler);
        mRecycler.clear();

        if (mIsAttached) {
            mLayout.dispatchDetachedFromWindow(this, mRecycler);
        }
        mLayout.setRecyclerView(null);
        mLayout = null;
    } else {
        mRecycler.clear();
    }
    // this is just a defensive measure for faulty item animators.
    mChildHelper.removeAllViewsUnfiltered();
    mLayout = layout;
    if (layout != null) {
    // 当第二次使用时,便会为true
        if (layout.mRecyclerView != null) {
            throw new IllegalArgumentException("LayoutManager " + layout
                    + " is already attached to a RecyclerView:"
                    + layout.mRecyclerView.exceptionLabel());
        }
        // !!!当第一次调用该方法时,layoutManager就已经跟RecycleView绑定了。第二次在另一个RecycleView中调用该方法就会抛出异常
        mLayout.setRecyclerView(this);
        if (mIsAttached) {
            mLayout.dispatchAttachedToWindow(this);
        }
    }
    mRecycler.updateViewCacheSize();
    requestLayout();
}
```
```