Epoxy - 在RecyclerView中构建复杂界面 - 7

440 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

图片预加载

Epoxy提供了通用的预加载机制, 可以在 Model 绑定之前为 View 内容开启后台拉取. 这对于需要展示的图片, 视频或者其它内容进行预加载是很有用处的.

目前 Epoxy 提供了 Glide 预加载, 但是对于其它库也能够很容易地创建预加载器.

Glide预加载

如果用Glide加载图片的话, 那么可以充分利用Epoxy的内置支持来方便地预加载Glide图片.

依赖

首先, 添加Epoxy的Glide预加载模块的依赖:

implementation 'com.airbnb.android:epoxy-glide-preloading:3.x.y' // 使用最新版本

定义预加载的ImageView

要想指定拥有预加载请求的ImageView, 需要在执行预加载操作的 Model 上添加Preloadable接口.

  • 如果EpoxyModel来自添加了@ModelView注解的 View, 那么 View 需要实现Preloadable接口
  • 如果Model使用了ViewHolder, 那么EpoxyHolder子类要实现Preloadable接口

上面 2 个例子中, viewsToPreload属性应该提供包含所有需要实现预加载功能的 ImageView 列表(大多数情况下, 只有一个ImageView, 但是如果需要的, 可以支持多个).

在RecyclerView上启用预加载

最后, 通过addGlidePreloader扩展函数在RecyclerView上注册Glide预加载器.

epoxyRecyclerView.addGlidePreloader(
    Glide.with(this), // Pass a Glide RequestManager
    preloader = glidePreloader { requestManager, epoxyModel: YourModelType_, viewData ->
         // Use the requestManager to build your image request and return it here.
         // It is important that the request returned here matches EXACTLY to the request
         // that will be executed when the model is bound, otherwise you won't get a cache hit!

         // The EpoxyModel that is being preloaded is provided, so you can use its
         // data to know which url to load.
         // The viewData can also be used to get optional metadata about the view.
    }
)

如果没有使用EpoxyRecyclerView的话, 也有个RecyclerView#addGlidePreloader扩展 - 唯一的不同是: 你需要手动提供自己的EpoxyController.

自定义

差不多了! 图片请求将会在 Model 绑定之前被执行. 这是设置预加载的最简单方式, 但如果有需要, 依然有空间提供自定义和灵活性. 可以查看addGlidePreloader的文档来查找更多细节, 也可以看一下epoxy-preloadersample的示例代码.

默认大小和绽放

要想获得最好的预加载性能, View的图片请求将必须精确地匹配预加载请求, 由此Glide才能够命中内存缓存. 要命中内存缓存, 两个请求需要拥有完全相同的图片尺寸, 转换, 缩放和其它选项设置.(bumptech.github.io/glide/doc/c…)

为此, Epoxy的实现会自动地探测ImageView的大小和缩放类型. 它通过匹配到的大小设置Glide预加载目标且应用了缩放转换来匹配ScaleType. 这应该对大部分通用场景有用, 但如果有需要的话, 也可以任意修改Glide预加载器.

调试

如果要查看预加载是否按预期工作, 需要看一下Glide的日志. (bumptech.github.io/glide/doc/d…)

首先, 通过命令行adb shell setprop log.tag.Engine VERBOSE启用冗余日志, 之后在 Logcat 中查看Glide Engine日志, 当你滚动预加载列表的时候. 图片第一次加载的时候, 你会看到开头为Engine: Started new load 的日志信息.

如果图片请求产生了, 且有缓存命中, 你会看到类似Engine: Loaded resource from cache or Engine: Loaded resource from active resources的消息.

当你滚动时, 检查正在加载的URL是否是列表中更下方且在屏幕之外的项. 这意味着预加载正在启动.

在你滚动新的Image到View时, 检查在日志中是否看到缓存命中. 如果似乎不是这个情形的话, 看一眼每次加载的缓存的 Key. 该 Key 以key: EngineKey开头. 查找在预加载请求和真实请求缓存 Key 之间的不同 - 这会给予你需要哪些改变的线索, 使得预加载匹配真实的请求.

预加载提示

大多数预加载的实现只会预热缓存, 所以在 Model 真的绑定的时候, 预加载会发出内容请求并命中缓存. 为此, 在预加载程序中执行的请求必须与视图中的请求完全匹配. 建议预加载请求和实际请求共享相同的代码路径.