MVVM
Model
Model refers either to a domain model, which represents real state content (an object-oriented approach), or to the data access layer, which represents content (a data-centric approach).
View
As in the MVC and MVP patterns, the view is the structure, layout, and appearance of what a user sees on the screen.
ViewModel
The view model is an abstraction of the view exposing public properties and commands. Instead of the controller of the MVC pattern, or the presenter of the MVP pattern, MVVM has a binder. In the view model, the binder mediates communication between the view and the data binder. The view model has been described as a state of the data in the model.
Binder
Declarative data and command-binding are implicit in the MVVM pattern. In the Microsoft solution stack, the binder is a markup language called XAML. The binder frees the developer from being obliged to write boiler-plate logic to synchronize the view model and view. When implemented outside of the Microsoft stack the presence of a declarative databinding technology is a key enabler of the pattern.
MVVM好处
MVC
Activity/Fragment既承担了View的责任,又承担了Controller的责任。所以一般较复杂的页面,Activity/Fragment通常几千行代码都是小意思,而且Controller混杂了View和业务逻辑,这样想对业务逻辑来做单元测试也是非常困难的。
MVP
引入Presenter,让Activity/Fragment做回真正的View。Presenter持有View的接口引用。Activity/Fragment值负责UI的事情,业务逻辑放到Presenter处理。Presenter只是持有View的接口,这样使得对Presenter做单元测试变得可能。
MVVM
MVVM对MVP的升级版本,使用DataBinding,Command,消息事件让架构更加灵活。
- 数据驱动
ViewModel只关心数据和业务逻辑,基本不需要做UI操作,是需要修改数据,databinding就能自动同步更新UI。UI的修改,又会自动同步到数据中。 - 低耦合
ViewModel不涉及任何UI操作和对UI控件的引用,就算你把TextView改成EditText,ViewModel几乎不需要改任何代码。 - 团队协作
View和ViewModel松散耦合,一个人做UI(XML + Activity),另外一个人做ViewModel 。 - 单元测试
比MVP更进一步,View和ViewModel的单元测试都很方便。
Android Architecture Components
ViewModel
ViewModel需要继承android.arch.lifecycle.ViewModel。为特定的UI组件提供数据,比如:Activity、Fragment等,并处理与业务的通讯,比如调用其他组件加载数据。ViewModel与View之间相互隔离,并且不受activity屏幕旋转导致activity重新创建的影响。
LiveData
View和ViewModel通过LiveData来传递消息和数据。LiveData是一个可观察的数据持有者,他可以让APP中的组件观察LiveData是否发生改变,而且不需要他们之前有严格的相互依赖关系。LiveData还会遵循应用程序组件(Activity,Fragment, Service)的生命周期状态来避免内存泄露,从而使你的APP不会消费太多的内存(LiveData是生命周期感知的。这意味着除非fragment是激活状态(onStart但是还没有onStop),要不然是不会发起回调的。当fragment调用onStop后, LiveData还会自动删除观察者。)。
Model
Repository代码Model层,可以通过Room框架操作数据库,或者通过调用http接口来获取数据。Repository返回LiveData到ViewModel。
详情请看:http://www.jianshu.com/p/b6d91bffcfa4
Google官方BasicSample代码分析
项目地址:https://github.com/googlesamples/android-architecture-components/tree/master/BasicSample
View和ViewModel通过LiveData串联起来,还需要注意以下规则:
- ViewModel不能关联到任何Activity、Fragment和android View,如果这样的话可能会引起内存泄露。因为View的整个生命周期都会保留一个ViewModel的引用。
ViewModel通过LiveData暴露数据,LiveData可以让你不用有严格的依赖关系跨越多个组件观察数据的变化。
View,官方例子中,订阅以下的LiveData数据。因为LiveData是生命周期感知的,如果观察者不是处于激活状态,它不会push数据更新给到他们,这样能够帮忙避免许多常见的问题。
// Update the list of products when the underlying data changes.
viewModel.getProducts().observe(this, new Observer<List<ProductEntity>>() {
@Override
public void onChanged(@Nullable List<ProductEntity> myProducts) {
if (myProducts != null) {
mBinding.setIsLoading(false);
mProductAdapter.setProductList(myProducts);
} else {
mBinding.setIsLoading(true);
}
}
});
mIsDatabaseCreated设置false(开始初始化数据库),ProductListViewModel接收到后转化为null传给ProductListFragment,ProductListFragment通过databinding在UI上显示Loading UI。
mIsDatabaseCreated设置为true(数据库初始化完成),ProductListViewModel接收到后,通过DatabaseCreator查询到List<Product> Livedata返回给ProductListFragment,ProductListFragment通过databinding去除Loading UI,并且设置mProductAdapter显示所有Product。