简评:我个人是没有试过在项目里大规模使用 Loader,如果你知道有基于 Loader 的大型项目或者库的话,可以交流下。: )
Loader 在 2011 年左右和 Android Honycomb 被一起推出。曾经是一个实际上不应该出现的问题的解决办法 – 如果在 Fragment 或 Activity 中执行异步任务时遇到了 configuration 变化。
但 Fragment 或 View 中应该只表示应用程序的状态和处理交互,而不去运行任何异步业务逻辑。
所以,Loader 是想要解决哪些问题?
Loader 运行在单独的线程上,以免出现 UI 无响应。
当有事件触发时,提供回调方法以简化线程管理。
Loader 能够保留并缓存数据,以免当 configuration 变化后重复查询。
Loader 能通过实现 observer 来观察底层数据源的变动。比如,CursorLoader 会自动注册一个 ContentObserver,从而在数据变动时触发 reload。
事实上,这些情况在今天都不能让你一定要用 Loader,所有这些都可以在你不「潜入」LoaderManager 这个黑盒子的情况下解决。
现在通过 Architecture Components 中的 ViewModel 可以更方便的解决跨 configuration 的数据缓存和持久化问题,其不受设备横竖屏切换影响,也可以很方便的直接调用 onCleared() 方法取消对数据的订阅,防止内存泄漏。
使用 Loader 还需要注意 Activity 和 Fragment 的生命周期,要在适当的时候提供结果。同样,Architecture Components 中的 LiveData 可以满足需求,其对生命周期敏感,只在数据发生变化并且有被监听的时候触发。结合 Room 你甚至可以不额外增加一行代码就实现对数据库数据变动的监听。同时,Google 也强烈建议使用 Room 而不是直接使用 SQLite 和避免使用 Cursor(Square 的 SQL Brite 也有同样的作用)。
Loader 最大的问题可能就是「鼓励」你把异步代码放到 Fragment 或者说 UI 层当中(Fragment 中很多代码都是为了支持 Loader)。
到目前 Google 只提供了 CursorLoader 和 AsyncTaskLoader 这两个 Loader 的实现类,或许也侧面证明了 Loader 的复杂。Mark Murphy(’The Busy Coder’s Guide to Android Development’ 的作者) 曾经尝试基于 Loader 实现一个库,但最终还是放弃了,并写了一篇很棒的文章来解释为什么。
此外,Loader 的相关代码还深深的包含在 Activity 和 Fragment 中,不能用 JUnit 来测试。
最近,Android Support Library 27.1.0 中也开始减少 Fragment 和 Loader 的耦合了。或许,是时候选择更好的替代方案了。
如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: https://leetcode.jp/是时候在-android-中抛弃-loader-了/