使用两个 RecyclerView 滚动页面(片段):最先进的技术以及回收情况如何?
Scrolling a page (fragment) with two RecyclerViews: State of the art & how about recycling?
我在一个布局中有两个 RecyclerView
。直到现在我都无法滚动页面本身,只能滚动每个RecyclerView
,感觉很奇怪。现在我想找出滚动带有两个 RecyclerView
的页面的最佳实践。我听说当我把它们放在 NestedScrollView
中时,它们就停止回收它们的视图了。
- 将
RecyclerView
放入 NestedScrollView
会禁用 RecyclerView
中的项目回收是真的吗?
- 特别是如果数字 1 为真,当前推荐的启用具有两个 Recyclerview 的页面滚动的方法是什么?
更新
这是我的布局。假设 recycler1
和 recycler2
不携带相关的项目,所以将它们放在一个 RecyclerView
中(使用不同的视图类型)对我来说在语义上是错误的。
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:text="first title"
app:layout_constraintBottom_toTopOf="@+id/recycler1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/text1"
tools:itemCount="3"
tools:listitem="@layout/item_category" />
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="24dp"
android:text="second title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/recycler1" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/text2"
tools:itemCount="3"
tools:listitem="@layout/item_category" />
</androidx.constraintlayout.widget.ConstraintLayout>
NestedScrollView
- 的确如此。 NestedScrollView
的重点是它计算整个回收器视图大小及其所有子项要做到这一点,它需要渲染列表的所有子项 - 因此实际上 Android 矛盾地无法 RecycleView
s 在 RecyclerView
中。对于没有分页的小列表还可以,但是对于大列表来说这是一个主要的性能问题。
该问题的解决方案在于设计(或程序设计)领域。不要使用两个 RecyclerView
,而是使用一个 two view types。第二种方法 - 将包含两个列表的屏幕分成两个屏幕,每个屏幕包含一个列表。
通常有两个需要相互滚动的列表是糟糕的设计 - 所以尽量避免这样的解决方案。
希望对您有所帮助。
这正是 ConcatAdapter
as per the Concatenate adapters sequentially with ConcatAdapter blog post 的用例:
ConcatAdapter
is a new class available in recyclerview:1.2.0-alpha02
which enables you to sequentially combine multiple adapters to be displayed in a single RecyclerView
. This enables you to better encapsulate your adapters rather than having to combine many data sources into a single adapter, keeping them focused and re-usable.
这允许您将布局编写为单个 RecyclerView
,它可以正确回收视图,同时保持每个单独的适配器(及其数据加载)独立。
在你的情况下,你应该考虑实际上有 4 个适配器 - 两个简单的标题(或你可以编写的相同 TitleAdapter
的两个实例),再加上每个以前的适配器。
然后你将通过传递所有 4 个适配器来构造你的 ConcatAdapter
以使一个可滚动 RecyclerView
:
val firstTitleAdapter = TitleAdapter("first title")
val firstListAdapter: FirstListAdapter = …
val secondTitleAdapter = TitleAdapter("second title")
val secondListAdapter: SecondListAdapter = …
val concatAdapter = ConcatAdapter(firstTitleAdapter, firstListAdapter,
secondTitleAdapter, secondListAdapter)
recyclerView.adapter = concatAdapter
我在一个布局中有两个 RecyclerView
。直到现在我都无法滚动页面本身,只能滚动每个RecyclerView
,感觉很奇怪。现在我想找出滚动带有两个 RecyclerView
的页面的最佳实践。我听说当我把它们放在 NestedScrollView
中时,它们就停止回收它们的视图了。
- 将
RecyclerView
放入NestedScrollView
会禁用RecyclerView
中的项目回收是真的吗? - 特别是如果数字 1 为真,当前推荐的启用具有两个 Recyclerview 的页面滚动的方法是什么?
更新
这是我的布局。假设 recycler1
和 recycler2
不携带相关的项目,所以将它们放在一个 RecyclerView
中(使用不同的视图类型)对我来说在语义上是错误的。
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:text="first title"
app:layout_constraintBottom_toTopOf="@+id/recycler1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/text1"
tools:itemCount="3"
tools:listitem="@layout/item_category" />
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="24dp"
android:text="second title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/recycler1" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/text2"
tools:itemCount="3"
tools:listitem="@layout/item_category" />
</androidx.constraintlayout.widget.ConstraintLayout>
NestedScrollView
- 的确如此。 NestedScrollView
的重点是它计算整个回收器视图大小及其所有子项要做到这一点,它需要渲染列表的所有子项 - 因此实际上 Android 矛盾地无法 RecycleView
s 在 RecyclerView
中。对于没有分页的小列表还可以,但是对于大列表来说这是一个主要的性能问题。
该问题的解决方案在于设计(或程序设计)领域。不要使用两个 RecyclerView
,而是使用一个 two view types。第二种方法 - 将包含两个列表的屏幕分成两个屏幕,每个屏幕包含一个列表。
通常有两个需要相互滚动的列表是糟糕的设计 - 所以尽量避免这样的解决方案。
希望对您有所帮助。
这正是 ConcatAdapter
as per the Concatenate adapters sequentially with ConcatAdapter blog post 的用例:
ConcatAdapter
is a new class available inrecyclerview:1.2.0-alpha02
which enables you to sequentially combine multiple adapters to be displayed in a singleRecyclerView
. This enables you to better encapsulate your adapters rather than having to combine many data sources into a single adapter, keeping them focused and re-usable.
这允许您将布局编写为单个 RecyclerView
,它可以正确回收视图,同时保持每个单独的适配器(及其数据加载)独立。
在你的情况下,你应该考虑实际上有 4 个适配器 - 两个简单的标题(或你可以编写的相同 TitleAdapter
的两个实例),再加上每个以前的适配器。
然后你将通过传递所有 4 个适配器来构造你的 ConcatAdapter
以使一个可滚动 RecyclerView
:
val firstTitleAdapter = TitleAdapter("first title")
val firstListAdapter: FirstListAdapter = …
val secondTitleAdapter = TitleAdapter("second title")
val secondListAdapter: SecondListAdapter = …
val concatAdapter = ConcatAdapter(firstTitleAdapter, firstListAdapter,
secondTitleAdapter, secondListAdapter)
recyclerView.adapter = concatAdapter