[Android] App架构指南之开山篇
本文译自Android开发者文档中Android Architecture Components视频介绍
科学上网观看完整视频
转载请注明出处
应开发者需求,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是一个可观察的数据容器。也就是说,他可以存储数据,还会在数据发生改变时提醒你,这样你就能及时更新UI。LiveData是一个可拓展的抽象类,更简单一点说,你可以使用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和Fragment。Lifecycle 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应用,看起来可能是这样的: