应开发者需求, Android Framework 团队撰写了一份 Android 应用构建指南, 还开发出了配套的构建组件这些组件可以持续存储数据管理生命周期模块化你的应用, 帮你避免内存泄漏, 还能让你不必去写无聊的模板代码
基本的 Android 应用需要将数据库与稳健的 UI 结合起来, 新的组件如 Room,ViewModel,LiveData,Lifecycle 让这个任务变得很简单他们被设计成像积木一样能彼此组合, 下面我们来看看他们是如何工作的:
Room
我们用 Room 处理数据库, 这是一个新的 SQLite 对象处理库, 想要用 Room 设置表, 我们可以定义一个 Plain Old Java Object(POJO), 随后我们用 @Entity 来标记这个 POJO, 并创建一个用 @PrimaryKey 标记的 Id
- @Entity
- public class Trail{
- public @PrimaryKey String id;
- public String name;
- pubklic double kilometers;
- public int difficulty;
- }
你需要为每个 POJO 定义一个数据访问对象 (DAO), 这里声明的方法代表 SQLite 命令, 用来与你的 POJO 数据互动
- @Dao
- public interface TrailDao{
- //Create,read,update,delete examples
- @Insert(onConflict = IGNORE)
- void insertTrail(Trail trail);
- @Query("SELECT * FROM Traail")
- public List<Trail> findAllTrails();
- @Update(onConflict = REPLACE)
- void updateTrail(Trail trail);
- @Query("DELETE FROM Trail")
- void deleteAll();
- }
现在来看看插入和查询的方法, Room 已经将你的 POJO 对象自动转化为相应的数据表, 这个过程是双向的 Room 还会在编译时校验你的 SQLite, 如果你拼错了什么东西, 或是引用了数据库中不存在的列, 它会显示一条有用的错误提示
LiveData
现在你有了 Room 数据库, 你还可以使用另一种构建组件: LiveData , 来监控数据库中的更改 LiveData 是一个可观察的数据容器也就是说, 他可以存储数据, 还会在数据发生改变时提醒你, 这样你就能及时更新 UILiveData 是一个可拓展的抽象类, 更简单一点说, 你可以使用 MutableLiveData 类如果你发出数值更改请求, 并更新了 MutableLiveData 的值, 它随后就会在你的 UI 中触发刷新更加强大的是, Room 自带对 LiveData 的支持, 你可以同时使用它们 修改你的 DAO 让它返回用 LiveData 类包装的对象
- @Dao
- public interface TrailDao{
- ....
- @Query("SELECT * FROM Traail")
- public LiveData<List<Trail>> findAllTrails();
- ....
- }
Room 会创建一个 LiveData 对象用来观察数据库, 然后你就可以写出这样的代码来更新你的 UI
- trailsLiveData.observe(this,trails ->{
- //Update UI, in this case a RecyclerView
- mTrailsRectclerAdapter.replaceItems(trails);
- mTrailsRectclerAdapter.notifyDataSetChanged();
- }
最终结果是 如果你的 Room 数据库更新了, 他会改动你的 LiveData 对象内的数据, 从而自动触发 UI 更新
Lifecycle
不得不说 LiveData 还有一项很棒的功能, 这个组件会留意到生命周期, 现在你也许会想, 能留意到生命周期的组件是什么东西? 我还担心你不会问呢! 通过神奇的生命周期观察, LiveData 可以了解到你的界面何时再屏幕上出现, 何时撤离屏幕, 是否已被销毁, 它不会向处于非激活状态的 UI 发送数据库更新
它有两个接口, 分别是: Lifecycle Owners 和
Lifecycle Observers
Lifecycle Owner 是指那些有生命周期的对象, 比如 Activity 和 FragmentLifecycle Observer 则会观察 Lifecycle Owner, 并且会收到关于生命周期变动的通知下面来简要介绍一下经过简化的 LiveData 代码
- abstract public class LiveData<T> implements LifecycleObserver{
- @OnLifecycleEvent(Lifecycle.Event.ON_START)
- void startup() {...}
- @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
- void cleanup() {...}
- }
它同时也是一个 Lifecycle Observer 被 @OnLifecycleEvent 标注的方法, 在相关的 Lifecycle Owiner 开启和停止时, 解决了初始化和销毁的问题这就允许 LiveData 对象解决自身的建立和销毁问题 UI 组件观察 LiveData,LiveData 组件则观察 Lifecycle Owner 对各位 Android 代码库设计师们, 我还有一点补充, 你们可以使用完全相同的生命周期观察代码, 来为你自己的代码库自动请求建立和销毁方法
ViewModel
现在还有一个问题需要解决, 你的应用在运行期间, 会经历多种配置变化, 这些变化会对 Activity 界面进行破坏和重建我们不想把 LiveData 的初始化绑定在生命周期的 Activity 上, 因为这会导致大量无用而重复的代码这方面的一个例子就是数据库查询, 每次你翻转手机时, 它都会被执行, 那么要怎么办呢? 你把你的 LiveData 和任意其他与 UI 有关的数据放在 ViewModel 里 ViewModel 是一类为 UI 组件提供数据并能经历多次配置更改而继续存在的对象创建 ViewModel 对象时, 你需要继承 ViewModel 类, 随后把所有 UI 中必需的数据放进 ViewModel 中
- public class TrailListViewModel extends AndroidViewModel{
- private AppDatabase mDatabase;
- private LiveData<List<Trail>> trails;
- public TrailListViewModel(Application application){
- super(application);
- //AppDatabase is a Room database singleton
- //Check the guide for more information
- mDatabase = AppDatabase.getDb(getApplication());
- trails = mDatabase.trailModel().findAllTrails();
- }
- //Getters and setters
- }
因为你在 ViewModel 内部为 UI 缓存了数据, 所以如果你的 Activity 因为配置更改而被重新创建了, 你的应用不会对数据库进行查询随后当你创建 Activity 或 Fragment 时, 你就可以引用相应的 ViewModel 并使用它
- //In onCreate
- trailListViewModel = ViewModelProviders.of(this)
- .get(TrailListViewModel.class);
- //Code to set up the RecyclerView omitted
- trailListViewModel.getTrails().observe(this,trails ->{
- mTrailsRectclerAdapter.replaceItems(trails);
- mTrailsRectclerAdapter.notifyDataSetChanged();
- }
当你第一次得到 ViewModel 时, 它是为你的 Activity 而生成的, 当你再次请求 ViewModel 时, 你的 Activity 会收到当初生成的 ViewModel 和 UI 缓存数据所以不会再有无用的数据库调用了
总结一下所有这些炫目的构建组件, 我们谈到了 Room, 这是一个为 SQLite 设计的对象处理库还有 LiveData, 它会在数据更改时通知你, 这样你就可以更新 UI 了重要的是它和 Room 协作顺畅, 所以你可以在数据库数据更改时, 轻松更新 UI 我们还谈到了 Lifecycle Observer 和 Owner, 他们可以让非 UI 对象观察生命周期事件最后我们还介绍了 ViewModel, 它会为你提供无法被配置更改破坏的数据对象他们共同组成了一套构建组件, 可以用来编写模块化的可测试的强健的 Android 应用你可以灵活地搭配运用它们, 也可以挑选自己需要的来采用, 但这些只是冰山一角而已事实上, 更加久经考验的 Android 应用, 看起来可能是这样的:
来源: https://juejin.im/post/5aa2982551882555642ba660