UI程序模块内部代码架构一直都是围绕着数据(Model)、逻辑(Logic)、视图(View)的分层和解耦不断发展进化。从最初的MVC到MVP,再到现在本文要讲的MVVM架构,三层结构没有发生根本变化,不同的是各层之间的交互方式及其产生的解耦程度的变化。
本文所讲主要内容是Google在Jetpack中提供的MVVM架构方案。
业务逻辑在ViewModel层实现,View层持有ViewModel对象,ViewModel对象持有和操作数据。View层调用ViewModel对象执行业务逻辑,读取数据进行运算并将运算结果输出到Model层。
Model数据的变化会触发UI的层更新,Model层通知View层通过观察者模式实现,不持有View对象。
以上的结构设计,结合依赖倒置和观察者模式等一些设计原则和模式,可以实现各层之间的深度解耦隔离。
关注点分离是面向对象的核心概念,可以作为我们开发和架构的指导性原则。下面一张图是Google官方推荐的代码架构,在这个架构的基础上,谷歌给出了自己的MVVM架构实现方案。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PgKowQRI-1590502963413)(Lifecycle.jpg)]
上面的一张图是Jetpack中Lifecycle的类图结构。Fragment和FragmentActivity都是LifecycleOwner接口的实现类,持有一个LifecycleRegistry对象。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NdPgLp42-1590502963415)(./view-model.jpg)]
ViewModel: 为Activity或者Fragment处理业务逻辑,准备和管理数据,也处理Activity和Fragment间的通讯。一个ViewModel被创建后有生命周期,换句话说,一个ViewModel不会因为他的宿主配置改变而被销毁。新的宿主会跟这个ViewModel重新连接。ViewModel类的目的是获得和保持Activity和Fragment需要的信息。Activity或者Fragment应该在ViewModel中能被观察状态改变。可以通过LiveData或者DataBinding实现。也可以通过自己的框架实现。ViewModel唯一的任务是管理UI的数据。ViewModel不要接触View树或者持有Activity或Fragment的引用。
ViewModel的管理机制。从上面的类图可以看出,ViewModel是通过ViewModelProvider和ViewModelStore进行保存和管理的。Android中FragmentActivity是ViewModelStoreOwner的实现类,提供 getViewModelStore() 方法获取所持有的ViewModelStore对象,下面贴出这个方法在FragmentActivity中的实现,看到ViewModelStore对象并不是在FragmentActivity对象中直接创建的,而是通过一个名为 FragmentActivity.NonConfigurationInstances 的类对象进行管理的,所以FragmentActivity对象持有的ViewModelStore对象是多个对象共同持有的,可以是同类型的也可以是不同了类型的,只要他们引用来自同一个 FragmentActivity.NonConfigurationInstances 对象即可。
ViewModelPorvider: 对象持有一个ViewModelStore对象和一个Factory对象,ViewModelStore通过HashMap存储ViewModel对象,Factory用户生成新的ViewModel对象,存入HashMap。默认ViewModelPorvider为每一个ViewModel类只能生成一个对象,在HashMap中对应的Key固定对应的。也可以通过制定不同的Key来生成多个对象。所以,在使用过程中ViewModel原则上不要直接创建,而是通过ViewModelProvider创建,尽管我们可以直接创建ViewModel对象。
// FragmentActivity
@NonNull
public ViewModelStore getViewModelStore() {
if (this.getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call.");
} else {
if (this.mViewModelStore == null) {
FragmentActivity.NonConfigurationInstances nc = (FragmentActivity.NonConfigurationInstances)this.getLastNonConfigurationInstance();
if (nc != null) {
this.mViewModelStore = nc.viewModelStore;
}
if (this.mViewModelStore == null) {
this.mViewModelStore = new ViewModelStore();
}
}
return this.mViewModelStore;
}
}
// ViewModelProvider中创建ViewModel对象
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
String canonicalName = modelClass.getCanonicalName();
if (canonicalName == null) {
throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
}
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
//noinspection unchecked
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
viewModel = mFactory.create(modelClass);
mViewModelStore.put(key, viewModel);
//noinspection unchecked
return (T) viewModel;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DqkYVnrf-1590502963417)(LiveData.jpg)]
LiveData是持有数据的类,在给定的Lifecycle内被观察,同时也是生命周期的观察者。前面讲到FragmentActivity和Fragment是LifecycleOwner的实现类,需要观察他们的生命周期的类是LifecycleObserver接口的实现类。
通过LiveData提供的 observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) 方法添加观察者,观察者实现 Observer 泛型接口,并提供这个观察者相关的生命周期(LifecycleOwner)。在观察者的生命周期活跃状态时,LiveData中数据的改变都会通知观察者。
下面贴出添加观察者的observe方法源码实现,可以看到LiveData也会通过 LifecycleBoundObserver 类管理与生命周期相关的观察者,在生命周期结束后,把观察者从列表中移除,既观察者会被取消订阅。
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
public interface GenericLifecycleObserver extends LifecycleObserver {
/**
* Called when a state transition event happens.
*
* @param source The source of the event
* @param event The event
*/
void onStateChanged(LifecycleOwner source, Lifecycle.Event event);
}
向LiveData注册观察者也可以不提供LifecycleOwner,这个观察者除非显式删除,否则会一直保留在观察者列表中。注册不关注生命周期的观察者使用 observeForever(@NonNull Observer observer) 方法,实现 Observer 泛型接口。
@MainThread
public void observeForever(@NonNull Observer<T> observer) {
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
wrapper.activeStateChanged(true);
}