Reputation: 3677
I am trying to have multiple RecyclerViews in a layout but I get the following error: "LayoutManager is already attached to a RecyclerView"
The Java code is:
@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;
}
The XML layout code is:
<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>
The MyLinearLayoutManager is a custom LinearLayoutManager I found online in order to solve the wrap-content issue of the SDK LinearLayoutManager.
Is there any way I can have multiple RecyclerViews in a single layout? It seems that I cannot attach more than one LayoutManagers per layout.
Any assistance would be very welcome :)
Upvotes: 53
Views: 22817
Reputation: 1
Possible options to fix this crash:
LayoutManager
in onViewCreated
of Fragment
:override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView.layoutManager = LinearLayoutManager(context)
}
LayoutManager
as a variable in Fragment
, then detach the instance from RecyclerView
in onDestroyView
:class MyFragment : Fragment() {
private val myLayoutManager by lazy { LinearLayoutManager(context) }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView.layoutManager = myLayoutManager
}
override fun onDestroyView() {
recyclerView.layoutManager = null
super.onDestroyView()
}
}
The second option will work, because the condition for throwing an exception will be false. Here is the code from the method setLayoutManager
of RecyclerView
:
...
if (layout != null) {
if (layout.mRecyclerView != null) { // will be false
throw new IllegalArgumentException("LayoutManager " + layout
+ " is already attached to a RecyclerView:"
+ layout.mRecyclerView.exceptionLabel());
}
mLayout.setRecyclerView(this);
if (mIsAttached) {
mLayout.dispatchAttachedToWindow(this);
}
}
Upvotes: 0
Reputation: 28799
I opened FragmentB from FragmentA. Then returned back to FragmentA and got this exception. I found an error. I created in onCreate
:
linearLayoutManager = LinearLayoutManager(requireContext())
and used in it onCreateView
:
view.recycler_view.layoutManager = linearLayoutManager
Because linearLayoutManager
hadn't recreated when we returned from FragmentB, RecyclerView
used an old linearLayoutManager
. So, I moved linearLayoutManager = LinearLayoutManager(requireContext())
to onCreateView
.
Upvotes: 4
Reputation: 11
I had this problem with Dagger2 and it was solved by removing the Scope Annotation. I had annotated the code with some scope and when i removed the scope the problem was fixed. I hope this would be helpful to you.
@MyScope @Provides static LinearLayoutManager provideLinearLayoutManager
I deleted the @MyScope
.
Upvotes: 1
Reputation: 281
This error I faced with Daggar2 and simply remove by using Provider before the LinearLayoutManager like;
@Inject
Provider <LinearLayoutManager> linearLayoutManager;
mViewDataBinding.rvResult.setLayoutManager(linearLayoutManager.get());
Upvotes: 0
Reputation: 2135
In my case, I had declared a LinearLayoutManager
globally and I was trying to attach the same instance of LinearLayoutManager
to multiple RecyclerView's
so I was getting this error.
The Solution is to attach different LayoutManager
to each RecyclerView
because one LayoutManager can only be attached to one Recyclerview
.
Upvotes: 3
Reputation: 4065
I faced this error when providing LayoutManager via Dagger.
The solution is to replace layout manager injection with layout manager javax.inject.Provider injection.
@Inject
lateinit var layoutManager: Provider<RecyclerView.LayoutManager>
...
recyclerView.setLayoutManager(layoutManager.get())
Upvotes: 9
Reputation: 1732
Just need to create a new instance:
RecyclerView recyclerView = new RecyclerView(getContext());
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()))
Upvotes: 9
Reputation: 2851
I have the same problem as well. I work around it by setting null to LinearLayoutManager instance.
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;
}
Upvotes: 4
Reputation: 1772
I had this problem too. My Activity uses Tabs, with three fragments, when I go to third tab, and back to first (or second), this error is thrown.
After searching a lot, I found out that may be the garbage collector, because I was using a strong reference.
Since the constructor LinearLayoutManager uses the activity as the parameter (not the fragment), a Tabs Activity stays active during tabs changes.
Removing the local field in mLinearLayoutManager from the class, and using a weak reference, I could get rid of this problem:
before:
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);
}
}
I changed to:
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()));
}
}
Upvotes: 100