Jetpack 中 MVVM 架构实战分析

一、背景介绍

UI程序模块内部代码架构一直都是围绕着数据(Model)、逻辑(Logic)、视图(View)的分层和解耦不断发展进化。从最初的MVC到MVP,再到现在本文要讲的MVVM架构,三层结构没有发生根本变化,不同的是各层之间的交互方式及其产生的解耦程度的变化。

本文所讲主要内容是Google在Jetpack中提供的MVVM架构方案。

MVVM的基础架构图

Jetpack 中 MVVM 架构实战分析_第1张图片 - View层负责UI展示和UI逻辑,不直接持有和操作数据。
  • 业务逻辑在ViewModel层实现,View层持有ViewModel对象,ViewModel对象持有和操作数据。View层调用ViewModel对象执行业务逻辑,读取数据进行运算并将运算结果输出到Model层。

  • Model数据的变化会触发UI的层更新,Model层通知View层通过观察者模式实现,不持有View对象。

    以上的结构设计,结合依赖倒置和观察者模式等一些设计原则和模式,可以实现各层之间的深度解耦隔离。

Google官方在Jetpack中列出了两条一般性的架构原则

  1. 关注点分离(Separation of Concerns)
  2. 数据驱动界面(Drive UI from a Model)

关注点分离是面向对象的核心概念,可以作为我们开发和架构的指导性原则。下面一张图是Google官方推荐的代码架构,在这个架构的基础上,谷歌给出了自己的MVVM架构实现方案。

Jetpack 中 MVVM 架构实战分析_第2张图片

二、Google版MVVM实现方案

  1. Lifecycle:管理Activity/Fragment的生命周期;
  2. ViewModel:以对生命周期敏感的方式,管理UI相关的数据,数据是LiveData形式;
  3. LiveData:基于观察者模式。在数据发生变化时通知UI更新或调起ViewModel层执行对应的逻辑处理。LiveData可以是对生命周期敏感的,也可以是不敏感的。

三、Google MVVM实现方案中各部分介绍

Lifecycle

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PgKowQRI-1590502963413)(Lifecycle.jpg)]

上面的一张图是Jetpack中Lifecycle的类图结构。Fragment和FragmentActivity都是LifecycleOwner接口的实现类,持有一个LifecycleRegistry对象。

  • LifecycleRegistry: LifecycleRegistry继成抽象基类Lifecycle,持有一个保存有View生命周期的枚举类型State类对象。Lifecycle支持注册观察者,所有需要关心View生命周期的类和对象都可以实现LifecycleOberver接口注册为Lifecycle对象的观察者,并在对应的状态做出相应的反应。
  • LifecycleOwner: Fragment和FragmentActivity是LifecycleOwner的实现类,通过 getLifecycle() 方法对外提供当前生命周期状态。查询生命周期的对象持有的并不是一个Fragment对象或者FragmentActivity对象,而是LifecycleOwner对象,这样实现了两种对象之间的解耦。

ViewModel

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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;
 }

LiveData

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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);
}

你可能感兴趣的:(安卓开发,前端)