【问题标题】:"LayoutManager is already attached to a RecyclerView" error“LayoutManager 已附加到 RecyclerView”错误
【发布时间】:2015-08-12 05:44:18
【问题描述】:

我试图在一个布局中包含多个 RecyclerView,但出现以下错误:“LayoutManager 已附加到 RecyclerView”

Java 代码是:

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

    Activity parentActivity = getActivity();
    final ObservableScrollView scrollView = (ObservableScrollView) view.findViewById(R.id.squad_scrollview);

    final RecyclerView gkRecyclerView = (RecyclerView) view.findViewById(R.id.gk_recycler);
    final RecyclerView coachRecyclerView = (RecyclerView) view.findViewById(R.id.coach_recycler);

    coachRecyclerView.setAdapter(new SquadRecyclerAdapter(parentActivity, getSquadDummyData(0)));
    coachRecyclerView.setLayoutManager(new MyLinearLayoutManager(parentActivity, LinearLayoutManager.VERTICAL, false));
    coachRecyclerView.setHasFixedSize(false);

    gkRecyclerView.setAdapter(new SquadRecyclerAdapter(parentActivity, getSquadDummyData(1)));
    gkRecyclerView.setLayoutManager(new MyLinearLayoutManager(parentActivity, LinearLayoutManager.VERTICAL, false));
    gkRecyclerView.setHasFixedSize(false);

    scrollView.setTouchInterceptionViewGroup((ViewGroup) parentActivity.findViewById(R.id.container));

    if (parentActivity instanceof ObservableScrollViewCallbacks) {
        scrollView.setScrollViewCallbacks((ObservableScrollViewCallbacks) parentActivity);
    }

    return view;
}

XML 布局代码为:

<com.github.ksoichiro.android.observablescrollview.ObservableScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/squad_scrollview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="@dimen/margin_medium"
    >

    <LinearLayout
        android:id="@+id/squad_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/seasons_scrollview"
        android:divider="@drawable/nav_bar_divider"
        android:elevation="@dimen/card_elevation"
        android:orientation="vertical"
        android:showDividers="middle">

        <LinearLayout
            android:id="@+id/coach_group"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingBottom="@dimen/margin_small"
            android:paddingLeft="@dimen/margin_standard"
            android:paddingRight="@dimen/margin_standard"
            android:paddingTop="@dimen/margin_small">

            <TextView
                android:id="@+id/squad_coach_header"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Coach"
                android:textSize="@dimen/text_size_standard" />

            <android.support.v7.widget.RecyclerView
                android:id="@+id/coach_recycler"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingTop="@dimen/margin_small"
                android:paddingBottom="@dimen/margin_small"
                android:scrollbars="none">

            </android.support.v7.widget.RecyclerView>

        </LinearLayout>

        <LinearLayout
            android:id="@+id/gk_group"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingBottom="@dimen/margin_small"
            android:paddingLeft="@dimen/margin_standard"
            android:paddingRight="@dimen/margin_standard"
            android:paddingTop="@dimen/margin_small">

            <TextView
                android:id="@+id/squad_gk_header"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Goalkeepers"
                android:textSize="@dimen/text_size_standard" />

            <android.support.v7.widget.RecyclerView
                android:id="@+id/gk_recycler"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingTop="@dimen/margin_small"
                android:paddingBottom="@dimen/margin_small"
                android:scrollbars="none">

            </android.support.v7.widget.RecyclerView>

        </LinearLayout>

        <LinearLayout
            android:id="@+id/def_group"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingBottom="@dimen/margin_small"
            android:paddingLeft="@dimen/margin_standard"
            android:paddingRight="@dimen/margin_standard"
            android:paddingTop="@dimen/margin_small">

            <TextView
                android:id="@+id/squad_def_header"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Defense"
                android:textSize="@dimen/text_size_standard" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/mid_group"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingBottom="@dimen/margin_small"
            android:paddingLeft="@dimen/margin_standard"
            android:paddingRight="@dimen/margin_standard"
            android:paddingTop="@dimen/margin_small">

            <TextView
                android:id="@+id/squad_mid_header"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Midfielders"
                android:textSize="@dimen/text_size_standard" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/for_group"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingBottom="@dimen/margin_small"
            android:paddingLeft="@dimen/margin_standard"
            android:paddingRight="@dimen/margin_standard"
            android:paddingTop="@dimen/margin_small">

            <TextView
                android:id="@+id/squad_for_header"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Forwards"
                android:textSize="@dimen/text_size_standard" />

        </LinearLayout>


    </LinearLayout>


</com.github.ksoichiro.android.observablescrollview.ObservableScrollView>

MyLinearLayoutManager是我在网上找到的一个自定义LinearLayoutManager,用于解决SDK LinearLayoutManager的wrap-content问题。

有什么方法可以在一个布局中拥有多个 RecyclerViews?似乎我不能为每个布局附加多个 LayoutManager。

非常欢迎任何帮助:)

【问题讨论】:

  • 你能用那个 LayoutManager 的源更新一下吗?
  • 我尝试了 SDK LinearLayoutManager 但仍然是同样的错误。所以这不是自定义 LayoutManager 的问题。

标签: android android-layout android-recyclerview


【解决方案1】:

我也有这个问题。我的 Activity 使用带有三个片段的选项卡,当我转到第三个选项卡并返回第一个(或第二个)选项卡时,会引发此错误。

查了很多,发现可能是垃圾回收器,因为我用的是强引用。

由于构造函数 LinearLayoutManager 使用活动作为参数(而不是片段),因此选项卡活动在选项卡更改期间保持活动状态。

从类中删除 mLinearLayoutManager 中的本地字段,并使用弱引用,我可以摆脱这个问题:

之前:

public class MyFragment1 extends Fragment
    private LinearLayoutManager linearLayoutManager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        linearLayoutManager = new LinearLayoutManager(getActivity());
        (...)
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        (...)
        mRecyclerView.setLayoutManager(linearLayoutManager);
    }
}

我改成:

public class MyFragment1 extends Fragment {
    // private LinearLayoutManager linearLayoutManager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // linearLayoutManager = new LinearLayoutManager(getActivity());
        (...)
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        (...)
        mRecyclerView.setLayoutManager(
           new LinearLayoutManager(getActivity()));
    }
}

【讨论】:

  • 不仅有效,我还设法在显示片段时根据用户选择更改布局,只需单击一个按钮。
  • 非常感谢!
  • 还有其他方法吗?因为我也需要在我的片段中使用 LayoutManager 作为全局对象
  • 如果我在 Fragment 类中需要 LayoutManager 怎么办?例如,我将它用于 scrollListeners
  • 当这样的答案解决了我如此具体的问题并提供了如此简单、直接的解决方案时,它是如此罕见,但如此令人满意。谢谢!
【解决方案2】:

只需要创建一个新实例:

RecyclerView recyclerView = new RecyclerView(getContext());
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()))

【讨论】:

    【解决方案3】:

    我在通过 Dagger 提供 LayoutManager 时遇到了这个错误。
    解决办法是用布局管理器javax.inject.Provider注入代替布局管理器注入。

    @Inject
    lateinit var layoutManager: Provider<RecyclerView.LayoutManager>
    
    ...
    
    recyclerView.setLayoutManager(layoutManager.get())
    

    【讨论】:

    • 哇,谢谢,所以每次调用 get() 时,Provider 都会创建一个新的...嗯
    • Provider 创建新的 layoutManager 实例
    【解决方案4】:

    我也有同样的问题。我通过将 null 设置为 LinearLayoutManager 实例来解决它。

    public class MyFragment extends Fragment {
    protected LinearLayoutManager mLinearLayoutManager;
    ...
    
    @Override
    public void onDestroy() {
        super.onDestroy();
        if(mLinearLayoutManager != null) // Workaround: android.support.v7.widget.LinearLayoutManager is already attached to a RecyclerView
            mLinearLayoutManager = null;
    }
    

    【讨论】:

      【解决方案5】:

      在我的例子中,我已经在全局范围内声明了一个 LinearLayoutManager,我试图将 LinearLayoutManager 的同一个实例附加到多个 RecyclerView's,所以我收到了这个错误。

      解决方案是为每个RecyclerView 附加不同的LayoutManager,因为一个LayoutManager 只能附加到一个Recyclerview

      【讨论】:

        【解决方案6】:

        我从 FragmentA 打开了 FragmentB。然后返回 FragmentA 并得到这个异常。我发现了一个错误。我在onCreate创建:

        linearLayoutManager = LinearLayoutManager(requireContext())
        

        并在其中使用onCreateView:

        view.recycler_view.layoutManager = linearLayoutManager
        

        因为当我们从 FragmentB 返回时 linearLayoutManager 尚未重新创建,RecyclerView 使用了旧的 linearLayoutManager。所以,我将linearLayoutManager = LinearLayoutManager(requireContext()) 移至onCreateView

        【讨论】:

          【解决方案7】:

          我在使用 Daggar2 时遇到的这个错误 只需在 LinearLayoutManager 之前使用 Provider 即可删除;

           @Inject
          
           Provider <LinearLayoutManager> linearLayoutManager;
          
           mViewDataBinding.rvResult.setLayoutManager(linearLayoutManager.get());
          

          【讨论】:

            【解决方案8】:

            我在使用 Dagger2 时遇到了这个问题,通过删除 Scope Annotation 解决了这个问题。 我已经用一些范围注释了代码,当我删除范围时,问题得到了解决。 希望对您有所帮助。

            @MyScope @Provides static LinearLayoutManager provideLinearLayoutManager

            我删除了@MyScope

            【讨论】:

              【解决方案9】:

              我通过以下步骤解决了这个问题(以防有人再次遇到它):

              清理项目

              重建项目

              使缓存无效

              之后我再次编译,它运行起来就像一个魅力

              PS:我不知道上面三个步骤中的哪一个成功了,因为我在编译之前一次尝试了它们。如果有人再次面对它并一次尝试这些步骤,请发布具体哪一步是问题的解决方案。

              【讨论】:

              • 对于 IllegalArgumentException 问题的公认答案没有任何意义。 @WilliamK 的回答可以帮助大家解决问题。
              • @Sniper 因为它帮助了许多用户 WilliamK 的回答我改变了接受的答案
              • 谢谢 Theok,不错的选择,因为当您尝试使用第二个或其他 RecyclerView 重用 LayoutManager 的相同实例时会发生此异常,我认为上面的答案正是这样做
              猜你喜欢
              • 2018-07-05
              • 2019-06-22
              • 2016-01-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-11-16
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多