使用Support库27.1.1,RecyclerView+NestedScrollView+BottomSheetBehavior性能不佳如何解决?
解决BottomSheet内RecyclerView带复杂自定义View的滑动性能问题
我之前也碰到过几乎一模一样的场景——BottomSheet里的RecyclerView加载带复杂onDraw的自定义View时,拖动滑栏卡顿得离谱。结合你的情况,咱们一步步拆解优化:
一、先啃自定义View的onDraw硬骨头
这绝对是性能瓶颈的核心,毕竟你提到了“复杂onDraw”:
- 禁止在onDraw里创建对象:像
Paint、Path、Rect这类工具类,一定要在构造方法或者onSizeChanged里提前初始化,别每次绘制都new,不然会频繁触发GC拖慢主线程。 - 缩小绘制范围:用
canvas.clipRect()把绘制区域严格限制在View的可见范围内,尤其是自定义View有部分被遮挡时,别做无用的绘制工作。 - 硬件加速赋能:给自定义View设置
setLayerType(View.LAYER_TYPE_HARDWARE, null),让GPU接管复杂绘制逻辑,但注意如果View有频繁的属性动画,要避免过度离屏渲染。 - 排查过度绘制:打开开发者选项里的“调试GPU过度绘制”,如果View显示红色/深红色,说明过度绘制严重,得砍掉不必要的背景、重叠绘制层级。
二、调整RecyclerView的适配配置
RecyclerView的按需复用本来是优势,但结合BottomSheet的滑动特性,默认配置可能不太适配:
- 固定Item尺寸:如果你的自定义View高度是固定的,务必给RecyclerView设置
setHasFixedSize(true),这样RecyclerView就不会每次滑动都重新计算布局尺寸,减少无效的requestLayout。 - 调大View缓存:默认的View缓存可能跟不上BottomSheet快速拖动的节奏,试试
recyclerView.setItemViewCacheSize(6)(数值可以根据Item大小调整,一般5-8个足够),滑出屏幕的View不会立即被回收,再次滑入时直接复用,省去重新绘制的开销。 - 解决嵌套滑动冲突:因为RecyclerView在NestedScrollView内部,可能出现滑动事件被拦截的情况,导致RecyclerView频繁触发布局。可以给RecyclerView设置
android:nestedScrollingEnabled="false",让NestedScrollView全权处理滑动,减少RecyclerView的不必要回调。 - 共享View复用池:如果多个页面用到这个自定义View,用
RecyclerView.setRecycledViewPool()共享View池,进一步提升复用效率。
三、优化BottomSheetBehavior的滑动逻辑
BottomSheet的状态切换也会带来额外性能开销:
- 简化状态流程:如果不需要折叠状态,给BottomSheetBehavior设置
setSkipCollapsed(true),减少状态切换时的布局计算。 - 滑动时动态降载:监听BottomSheet的滑动状态,当处于
STATE_DRAGGING(拖动中)时,暂时简化自定义View的onDraw逻辑(比如跳过非核心的绘制步骤),等滑动停止(STATE_EXPANDED或STATE_COLLAPSED)再恢复完整绘制。示例代码大概是这样:bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { @Override public void onStateChanged(@NonNull View bottomSheet, int newState) { boolean isDragging = newState == BottomSheetBehavior.STATE_DRAGGING; // 给自定义View传递标记,控制绘制复杂度 recyclerView.getAdapter().notifyDataSetChanged(); } @Override public void onSlide(@NonNull View bottomSheet, float slideOffset) {} }); - 稳定NestedScrollView布局:给NestedScrollView添加
android:fillViewport="true",确保它填满父容器,避免BottomSheet滑动时布局反复调整。
四、版本升级(可选但推荐)
你用的Support库27.1.1相对较旧,里面可能存在BottomSheet和RecyclerView交互的已知性能bug。建议升级到AndroidX对应版本(比如androidx.appcompat:appcompat:1.6.1),Google在后续版本里修复了不少嵌套滑动和布局优化的问题,说不定升级后卡顿问题就解决了大半。
最后提醒下:一定要用Android Studio的Profiler工具定位具体卡顿点——看看是主线程被绘制占用,还是GC频繁,或是布局耗时过长,针对性优化才最高效。
内容的提问来源于stack exchange,提问作者l33t
相关产品推荐
相关产品推荐

