RecyclerView嵌套NestedScrollView时调用所有Item的onBindViewHolder()问题咨询
解决RecyclerView嵌套NestedScrollView时全量调用onBindViewHolder的问题
我太懂这种烦恼了——本来想用RecyclerView的复用机制优化性能,结果嵌套进NestedScrollView后,所有Item一下子都触发了onBindViewHolder,完全失去了复用的意义。先给你拆解下原因,再给几个靠谱的解决方案:
问题根源
你的布局里NestedScrollView设置了android:fillViewport="true",这会让它强制把内部的RecyclerView拉伸到和自身一样高。RecyclerView的LayoutManager看到需要填充这么大的高度,就会认为所有Item都需要显示出来,自然就会一次性调用所有Item的onBindViewHolder了。
解决方案
方案1:移除NestedScrollView(最优解)
如果你的布局里只有RecyclerView需要和AppBarLayout配合滚动,那完全没必要用NestedScrollView,直接把RecyclerView作为CoordinatorLayout的子View,给它加上AppBar的滚动行为就行。这样既保留了RecyclerView的复用特性,又能完美配合AppBar的滚动:
<CoordinatorLayout xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_scrollFlags="scroll|enterAlways"/> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> </CoordinatorLayout>
方案2:保留NestedScrollView的情况下优化
如果你的布局里还有其他View(比如顶部的介绍文本、按钮)需要和RecyclerView一起滚动,必须保留NestedScrollView,那可以这么做:
- 给RecyclerView设置
android:nestedScrollingEnabled="false",让它把滚动事件交给NestedScrollView处理; - 确保RecyclerView的高度设置为
wrap_content; - (可选)如果用的是LinearLayoutManager,也可以自定义一个禁止自身滚动的LayoutManager,避免滚动冲突:
public class NoScrollLinearLayoutManager extends LinearLayoutManager { public NoScrollLinearLayoutManager(Context context) { super(context); } @Override public boolean canScrollVertically() { return false; } }
然后在代码里给RecyclerView设置这个LayoutManager:
recyclerView.setLayoutManager(new NoScrollLinearLayoutManager(this));
这样调整后,RecyclerView就只会加载当前可见区域的Item,不会一次性全量绑定了。
内容的提问来源于stack exchange,提问作者MaaAn13
相关产品推荐
相关产品推荐

