在 Android 应用程序中,RecyclerView 是一个非常重要的控件。它被广泛运用,由于它可以协助我们展现很多的数据,一同也可以供给流通的滑动体会。但是,假如我们不小心处理好 RecyclerView 的缓存机制,就可能会导致功用下降或许内存走漏的问题。
RecyclerView 的缓存类型
RecyclerView 中有三种缓存类型:View Cache,Scrap Cache 和 ViewPool。
View Cache
View Cache 指的是 RecyclerView 在屏幕上现已展现的 View 的缓存。这些 View 被缓存起来,以便在需求的时分可以快速地进行重用。View Cache 的巨细是由 LayoutManager 来操控的。
Scrap Cache
Scrap Cache 指的是 RecyclerView 在滑动进程中,从屏幕中移除的 View 的缓存。这些 View 被缓存起来,以便在需求的时分可以快速地进行重用。Scrap Cache 的巨细不是由 LayoutManager 来操控的,而是由 RecyclerView 自己保护的。
ViewPool
ViewPool 答应你保护一个 ViewHolder 的缓存池,让你的 RecyclerView 在需求“快速翻页”,或是动态更新内容的时分,可以快速的完结这些操作。当 ViewPool 里的缓存满了之后,多余的会被收回删除去。
RecyclerView 的缓存机制怎么作业
RecyclerView 的缓存机制作业流程如下:
-
当 RecyclerView 需求展现一个新的 View 时,它会首先从 View Cache 中查找是否有可重用的 View。假如有,它会将这个 View 从 View Cache 中移除,并将其回来给 LayoutManager 进行重用。
-
假如 View Cache 中没有可重用的 View,RecyclerView 会从 Scrap Cache 中查找是否有可重用的 View。假如有,它会将这个 View 从 Scrap Cache 中移除,并将其回来给 LayoutManager 进行重用。
-
假如 Scrap Cache 中也没有可重用的 View,RecyclerView 会调用 LayoutManager 的 createViewHolder() 办法创立一个新的 ViewHolder,并将其回来给 RecyclerView 进行展现。
-
当一个 ViewHolder 不再需求展现时,RecyclerView 会将其参加到 Scrap Cache 中,以便在需求的时分可以快速地进行重用。
-
在布局进程中,LayoutManager 可以从 ViewPool 中获取可重用的 ViewHolder,并且将其放回 ViewPool 中以便在需求的时分可以快速的获取。
-
当 RecyclerView 被毁掉时,所有的 View 都会被开释,并且 Scrap Cache 也会被清空。
需求留意的是,RecyclerView 的缓存机制是经过弱引用完成的。所以,当 Java 废物收回器决议铲除一个 ViewHolder 的时分,它会被自动整理掉。这就意味着,假如你的 ViewHolder 需求重新绑定数据,就必须在 RecyclerView 中手动调用 onBindViewHolder 办法。
怎么优化 RecyclerView 的缓存机制
为了优化 RecyclerView 的缓存机制,我们可以采取以下措施:
削减 ViewHolder 的创立次数和内存占用
可以运用 DataBinding 或 ButterKnife 等方式来简化视图绑定逻辑,进步代码可读性和保护性。别的,关于数据改变频率比较小且 ViewHolder 款式固定的情况,可以运用静态内部类(Static Inner Class)来定义 ViewHolder,经过 static 关键字修饰内部类,防止 ViewHolder 类重新加载导致的额定功用损耗。
运用 setItemPrefetchEnabled() 办法敞开预取功用
在 LayoutManager 中运用 setItemPrefetchEnabled() 办法敞开预取功用,以提早加载屏幕外的数据,防止滑动卡顿现象,并且优化 RecyclerView 的缓存机制。
收回 ViewHolder 资源
在 RecyclerView.Adapter 中重写 onViewRecycled() 办法,以便在 ViewHolder 从屏幕中移除后收回其资源。这样可以更好地开释内存,然后防止内存泄漏的问题。
运用多个 RecyclerView.Adapter 来处理不同类型的数据
关于不同类型的数据,运用不同的布局文件和 ViewHolder,然后更好地利用缓存池机制,并且防止不同类型数据混搭反常。
DiffUtil 东西
在 RecyclerView.Adapter 中运用 DiffUtil 东西来比较新旧数据集的差异,然后防止不必要的数据更新和 ViewHolder 重建,进步 RecyclerView 的功用和呼应速度。
操控 RecyclerView 的滑动速度
RecyclerView 的滑动速度可能会影响它的功用和呼应性。假如滑动速度过快,可能会导致 RecyclerView 不能及时地重用 View 或许加载新的数据。为了操控滑动速度,我们可以运用 RecyclerView.SmoothScroller 类或许自定义 Scroller 类来完成。
防止在 onBindViewHolder 办法中执行耗时操作
onBindViewHolder 办法应该尽量简练,不要包含任何耗时操作,比方 I/O 操作、网络请求等。这样可以防止 RecyclerView 的功用下降和卡顿现象。假如 onBindViewHolder 中需求进行耗时操作,可以将它们放到子线程中进行,或许运用 LiveData、RxJava 等异步结构进行处理。
运用 RecyclerView.ItemAnimator 类
RecyclerView.ItemAnimator 类可以协助我们完成 View 的动画作用,比方淡入淡出、平移等。这些动画可以进步用户体会,但是要留意不要运用过多的动画,否则可能会影响 RecyclerView 的功用和呼应性。
经过设置 RecyclerView 的 ItemAnimator,可以在 RecyclerView 的添加删除动作时显现动效,让用户更好的体会到Item之间改变的进程。可以运用默许的 ItemAnimator 类,也可以自定义 ItemAnimator 类。自定义 ItemAnimator 类需求完成 RecyclerView.ItemAnimator 类并覆盖其中的办法,以操控适当的动画作用。
运用 setHasFixedSize() 办法
在 RecyclerView 初始化时调用 setHasFixedSize() 办法,可以告知 RecyclerView 什么时分它的巨细不会发生改变。这样可以防止 RecyclerView 不必要的布局核算,然后进步它的功用和呼应性。
经过将 setHasFixedSize() 办法设置为 true,可以告知 RecyclerView 它的巨细是固定的,不会发生改变。这可以让 RecyclerView 防止额定的布局核算,进步功用。但是要留意,假如你的 RecyclerView 的巨细的确会发生改变,那么就不要设置 setHasFixedSize() 办法为 true。
结论
在 Android 开发中,RecyclerView 是一个非常重要的控件。它可以协助我们展现很多的数据,一同也可以供给流通的滑动体会。在运用 RecyclerView 时,我们要了解其缓存机制,并且依据实际情况进行优化,然后进步 RecyclerView 的功用和呼应速度。
推荐
android_startup: 供给一种在应用发动时可以愈加简略、高效的方式来初始化组件,优化发动速度。不只支撑Jetpack App Startup的全部功用,还供给额定的同步与异步等待、线程操控与多进程支撑等功用。
AwesomeGithub: 根据Github的客户端,纯操练项目,支撑组件化开发,支撑账户暗码与认证登陆。运用Kotlin言语进行开发,项目架构是根据JetPack&DataBinding的MVVM;项目中运用了Arouter、Retrofit、Coroutine、Glide、Dagger与Hilt等盛行开源技能。
flutter_github: 根据Flutter的跨渠道版本Github客户端,与AwesomeGithub相对应。
android-api-analysis: 结合具体的Demo来全面解析Android相关的知识点, 协助读者可以更快的掌握与了解所论述的关键。
daily_algorithm: 每日一算法,由浅入深,欢迎参加一同共勉。