Android Jetpack框架之LiveData与ViewModel分析与使用

1、前言

Google 为了帮助 Android 开发者更快更好地开发 App,推出了一系列组件,这些组件被打包成了一个整体,称作 Android Jetpack,它包含的组件如下图所示

框架图
jetpack概览

官方对应 Architecture 的说明:

Android architecture components are a collection of libraries that help you design robust, testable, and maintainable apps. Start with classes for managing your UI component lifecycle and handling data persistence.
Manage your app's lifecycle with ease. New lifecycle-aware components help you manage your activity and fragment lifecycles. Survive configuration changes, avoid memory leaks and easily load data into your UI.
Use LiveData to build data objects that notify views when the underlying database changes.
ViewModel Stores UI-related data that isn't destroyed on app rotations.
Room is an a SQLite object mapping library. Use it to Avoid boilerplate code and easily convert SQLite table data to Java objects. Room provides compile time checks of SQLite statements and can return RxJava, Flowable and LiveData observables.

翻译:

Android体系结构组件是一组库,可帮助您设计健壮,可测试和可维护的应用程序。 从用于管理UI组件生命周期和处理数据持久性的类开始。
轻松管理应用程序的生命周期。 新的生命周期感知组件可帮助您管理活动和碎片生命周期。 生存配置更改,避免内存泄漏并轻松将数据加载到UI中。
使用LiveData构建数据对象,以便在基础数据库更改时通知视图。
ViewModel存储在应用程序轮换中未销毁的UI相关数据。
Room是一个SQLite对象映射库。 使用它来避免样板代码并轻松地将SQLite表数据转换为Java对象。 Room提供SQLite语句的编译时检查,可以返回RxJava,Flowable和LiveData observable。

官方推荐的应用架构指南

常见架构原则
1.分离关注点
要遵循的最重要的原则是分离关注点一种常见的错误是在一个 Activity 或 Fragment中编写所有代码。这些基于界面的类应仅包含处理界面和操作系统交互的逻辑。应尽可能使这些类保持精简,这样可以避免许多与生命周期相关的问题。

请注意,您并不拥有 Activity 和 Fragment的实现,这些只是表示 Android 操作系统与应用之间关系的粘合类。操作系统可能会根据用户交互或因内存不足等系统条件随时销毁它们。为了提供令人满意的用户体验和更易于管理的应用维护体验,最好尽量减少对它们的依赖。
2.用过模型驱动界面
另一个重要原则是您应该通过模型驱动界面,最好是持久性模型。模型是负责处理应用数据的组件。它们独立于应用中的 View 对象和应用组件,因此不受应用的生命周期以及相关关注点的影响。
持久性是理想之选,原因如下

  • 如果 Android 操作系统销毁应用以释放资源,用户不会丢失数据。
  • 当网络连接不稳定或不可用时,应用会继续工作。

应用所基于的模型类应明确定义数据管理职责,这样将使应用更可测试且更一致。

看下图,该图显示了设计应用后所有模块应如何交互


架构指南图

请注意,每个组件仅依赖于其下一级的组件。例如,Activity 和 Fragment 仅依赖于视图模型。存储区是唯一一个依赖于其他多个类的类;在本例中,存储区依赖于持久性数据模型和远程后端数据源。

这种设计打造了一致且愉快的用户体验。无论用户是在上次关闭应用几分钟后还是几天后回到应用,他们都会立即看到应用在本地保留的用户信息。如果此数据已过时,则应用的存储区模块将开始在后台更新数据。

2、介绍LiveData与ViewModel

ViewModel类旨在以生命周期意识的方式存储和管理与UI相关的数据。 ViewModel类允许数据在配置更改(例如屏幕旋转)后继续存在。
示例代码

public class FlowerModel extends ViewModel {    private MutableLiveData liveData;    public MutableLiveData getLiveData() {        if (liveData == null){            liveData = new MutableLiveData<>();        }        return liveData;    }    public static class Data {        public int send;        public int less;        public List list;    }}
flowerModel = ViewModelProviders.of(getActivity()).get(FlowerModel.class);

然后利用LiveData通知界面更新UI
LiveData 是一种可观察的数据存储器。应用中的其他组件可以使用此存储器来监控对象的更改,而无需在它们之间创建明确且严格的依赖路径。LiveData 组件还遵循应用组件(如 Activity、Fragment 和 Service)的生命周期状态,并包括清理逻辑以防止对象泄漏和过多的内存消耗。

  flowerModel.getLiveData().observe(getActivity(), new Observer() {            @Override            public void onChanged(@Nullable FlowerModel.Data data) {                //update UI            }        });

Demo演示

3、项目中应用

4、浅析原理与使用

ViewModel生命周期

  • ViewModel对象的范围是在获取ViewModel时传递给ViewModelProvider的Lifecycle生命周期-
  • ViewModel在内存中直到Activity销毁或Fragment被移除
  • 系统首次调用活动对象的onCreate()方法时,通常会请求ViewModel
  • 系统可能会在整个活动的整个生命周期中多次调用onCreate(),例如当设备屏幕旋转时
  • ViewModel从第一次请求ViewModel直到活动完成并销毁时存在
    ViewModel生命周期图
    看源码
    1,获取ViewModelProvider
    ViewModelProviders提供四个构造方法创建VIewProvider,两个带有factory两个没有,不过没有factory的其实使用的是默认的Factory,所以四个方法基本一致只是Fragment和Activity的区分
@NonNull    @MainThread    public static ViewModelProvider of(@NonNull Fragment fragment) {        return of(fragment, null);    }    @NonNull    @MainThread    public static ViewModelProvider of(@NonNull FragmentActivity activity) {        return of(activity, null);    }    @NonNull    @MainThread    public static ViewModelProvider of(@NonNull Fragment fragment, @Nullable Factory factory) {        Application application = checkApplication(checkActivity(fragment));        if (factory == null) {            factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);        }        return new ViewModelProvider(ViewModelStores.of(fragment), factory);    }    @NonNull    @MainThread    public static ViewModelProvider of(@NonNull FragmentActivity activity,            @Nullable Factory factory) {        Application application = checkApplication(activity);        if (factory == null) {            factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);        }        return new ViewModelProvider(ViewModelStores.of(activity), factory);    }

获取ViewModelStore:由前面的源码可以知道创建ViewProvider时传入两个参数:ViewModelStore 和 Factory;显然从名字就可以看出他们的作用,Factory负责创建,ViewModelStore负责存储

@NonNull    @MainThread    public  T get(@NonNull String key, @NonNull Class 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;    }

上面的执行是,先去ViewModelStore中获取,如果为空就调用Factory的create()创建ViewModel,并储存在VIewmoStore中

ViewModelProviders.of(SquareFragment.this).get(AudioLiveData.class)的执行流程大概图 忽略创建和存储细节

viewModel创建1

2,通过ViewModelStores.of(this)创建ViewModelStore 源码

    private ViewModelStores() {    }    @NonNull    @MainThread    public static ViewModelStore of(@NonNull FragmentActivity activity) {        if (activity instanceof ViewModelStoreOwner) {            return ((ViewModelStoreOwner) activity).getViewModelStore();        }        return holderFragmentFor(activity).getViewModelStore();    }    @NonNull    @MainThread    public static ViewModelStore of(@NonNull Fragment fragment) {        if (fragment instanceof ViewModelStoreOwner) {            return ((ViewModelStoreOwner) fragment).getViewModelStore();        }        return holderFragmentFor(fragment).getViewModelStore();    }

先判断Activity是否为 ViewModelStoreOwner,如果是直接获取其中的ViewModelStore,否则调用holderFragmentFor(activity).getViewModelStore()获取

    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)    public static HolderFragment holderFragmentFor(FragmentActivity activity) {        return sHolderFragmentManager.holderFragmentFor(activity);    }...    HolderFragment holderFragmentFor(FragmentActivity activity) {            FragmentManager fm = activity.getSupportFragmentManager();            //通过manager.findFragmentByTag(HOLDER_TAG)找到fragment            HolderFragment holder = findHolderFragment(fm);            if (holder != null) {                return holder;            }            holder = mNotCommittedActivityHolders.get(activity);            //在map中取            if (holder != null) {                return holder;            }            if (!mActivityCallbacksIsAdded) {                mActivityCallbacksIsAdded = true;                activity.getApplication().registerActivityLifecycleCallbacks(mActivityCallbacks);            }            //创建 HolderFragment            holder = createHolderFragment(fm);            //存到map中            mNotCommittedActivityHolders.put(activity, holder);            return holder;        }

其中 findHolderFragment

private static HolderFragment findHolderFragment(FragmentManager manager) {            if (manager.isDestroyed()) {                throw new IllegalStateException("Can't access ViewModels from onDestroy");            }            Fragment fragmentByTag = manager.findFragmentByTag(HOLDER_TAG);            if (fragmentByTag != null && !(fragmentByTag instanceof HolderFragment)) {                throw new IllegalStateException("Unexpected "                        + "fragment instance was returned by HOLDER_TAG");            }            return (HolderFragment) fragmentByTag;        }

map中get

@SuppressWarnings("WeakerAccess")    static class HolderFragmentManager {        private Map mNotCommittedActivityHolders = new HashMap<>();        private Map mNotCommittedFragmentHolders = new HashMap<>();...    holder = mNotCommittedActivityHolders.get(activity);

createHolderFragment

private static HolderFragment createHolderFragment(FragmentManager fragmentManager) {            HolderFragment holder = new HolderFragment();            fragmentManager.beginTransaction().add(holder, HOLDER_TAG).commitAllowingStateLoss();            return holder;        }

3, HolderFragment存储ViewModelStore
上面都是获取或者创建HolderFragment的过程,有没有想过我们存储ViewModel的地方,为什么一直在操作fragment ?我们回头看创建ViewModelStore的地方
有这么个判断 activity instanceof ViewModelStoreOwner

@NonNull    @MainThread    public static ViewModelStore of(@NonNull FragmentActivity activity) {        if (activity instanceof ViewModelStoreOwner) {            return ((ViewModelStoreOwner) activity).getViewModelStore();        }        return holderFragmentFor(activity).getViewModelStore();    }...public interface ViewModelStoreOwner {    @NonNull    ViewModelStore getViewModelStore();}

而HolderFragment实现了ViewModelStoreOwner,同时保存了ViewModelStore

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)public class HolderFragment extends Fragment implements ViewModelStoreOwner {...private ViewModelStore mViewModelStore = new ViewModelStore();@NonNull    @Override    public ViewModelStore getViewModelStore() {        return mViewModelStore;    }

ViwModelStore 利用HashMap获取,存储 ViewModel

public class ViewModelStore {    private final HashMap mMap = new HashMap<>();    final void put(String key, ViewModel viewModel) {        ViewModel oldViewModel = mMap.put(key, viewModel);        if (oldViewModel != null) {            oldViewModel.onCleared();        }    }    final ViewModel get(String key) {        return mMap.get(key);    }    public final void clear() {        for (ViewModel vm : mMap.values()) {            vm.onCleared();        }        mMap.clear();    }}

获取ViewModelStore的整体执行流程


ViewModelStore创建2

总结一下ViewModel内部的存储逻辑

  • 根据传入的Activity/Fragment获取、创建、添加并以activity为键保存Fragment(因此在屏幕发生旋转时生命周期改变两次创建activity时获取的都是同一个fragment因为key相同)
  • 获取Fragment中保存的ViewModelStore对象(ViewModelStore中使用Map储存ViewModel)
  • 创建ViewModelProvider实例,ViewModelProvider中封装了获取的ViewModelStore和创建用的Factory
  • 从VIewModelStore的Map中或Factory的create()中获取ViewModel

LiveData 是一个观察者模型,但是它是一个与 Lifecycle 绑定了的 Subject,也就是说,只有当 UI 组件处于 ACTIVE 状态时,它的 Observer 才能收到消息,否则会自动切断订阅关系

  • LiveData 只要有数据更新,它的 observer 就会收到通知。如果我们要把 LiveData 用作事件总线(类似EventBus),还需要做一些定制,可以使用google官方demo里的 SingleLiveEvent 。
public class SingleLiveEvent extends MutableLiveData {    private static final String TAG = "SingleLiveEvent";    private final AtomicBoolean mPending = new AtomicBoolean(false);    @MainThread    public void observe(LifecycleOwner owner, final Observer observer) {        if (hasActiveObservers()) {            Log.w(TAG, "Multiple observers registered but only one will be notified of changes.");        }        // Observe the internal MutableLiveData        super.observe(owner, new Observer() {            @Override            public void onChanged(@Nullable T t) {                if (mPending.compareAndSet(true, false)) {                    observer.onChanged(t);                }            }        });    }    @MainThread    public void setValue(@Nullable T t) {        mPending.set(true);        super.setValue(t);    }    /**     * Used for cases where T is Void, to make calls cleaner.     */    @MainThread    public void call() {        setValue(null);    }}
  • 我们没法直接修改 LiveData 的 value,因为它是不可变的(immutable),可变(mutable)版本是 MutableLiveData,通过调用 setValue(主线程)或 postValue(非主线程)可以修改它的 value
  • LiveData 有一个实现了中介者模式的子类 —— MediatorLiveData,它可以把多个 LiveData 整合成一个,只要任何一个 LiveData 有数据变化,它的观察者就会收到消息

汇总一下 LiveData 的使用场景:

* LiveData - immutable 版本*
* MutableLiveData - mutable 版本
* MediatorLiveData - 可汇总多个数据源
* SingleLiveEvent - 事件总线

LiveData转换

  • Transformations.map 对存储在LiveData对象中的值修改,并将结果发送到下游
 private class User{        private User(String id){ this.userId = id; }        private String userName;        private String userId;    }    private MutableLiveData userMutableLiveData;    public void test(){        userMutableLiveData = new MutableLiveData<>();        LiveData userName = Transformations.map(userMutableLiveData, new Function() {            @Override            public String apply(User input) {                return "姓名"+input.userName;            }        });
  • Transformations.switchMap 动态返回LiveData
private class User{        private User(String id){ this.userId = id; }        private String userName;        private String userId;    }    private MutableLiveData userMutableLiveData;    public void test(){        userMutableLiveData = new MutableLiveData<>();        LiveData userId = new MutableLiveData<>();        LiveData user2 = Transformations.switchMap(userId, new Function>() {            @Override            public LiveData apply(String input) {                return getUser(input);            }        });    }    private LiveData getUser(String id){        User user = new User(id);         userMutableLiveData.setValue(user);         return userMutableLiveData;    }

MutableLiveData只是LiveData的一个扩展类,重写了LiveData中的protected方法postValue()和setValue(),调用了super.postValue()和super.setValue(),也就是说所有的方法都是在LiveData中实现

@SuppressWarnings("WeakerAccess")public class MutableLiveData extends LiveData {    @Override    public void postValue(T value) {        super.postValue(value);    }    @Override    public void setValue(T value) {        super.setValue(value);    }}

先看 observe(@NonNull LifecycleOwner owner, @NonNull Observer observer)

flowerModel.getLiveData().observe(getActivity(), new Observer() {            @Override            public void onChanged(@Nullable FlowerModel.Data data) {                //update UI                            }        });... @MainThread    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {        if (owner.getLifecycle().getCurrentState() == DESTROYED) {            // 如果已经销毁就返回            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);    }
  • 在observe中首先判断了当前Lifecycler的状态,当Destroy时即观察者不处于活跃状态,不用接收数据
  • 创建LifecycleBoundObserver实例保存传入的LifecycleOwner和Observer,并保存在mObservers
  • 添加LifecycleOwner的观察者,响应生命周期的变化
    继续看 LifecycleBoundObserver
 private abstract class ObserverWrapper {        final Observer mObserver;        boolean mActive;        int mLastVersion = START_VERSION;        ObserverWrapper(Observer observer) {          //保存观察者Observer            mObserver = observer;        }        abstract boolean shouldBeActive();        boolean isAttachedTo(LifecycleOwner owner) {            return false;        }        void detachObserver() {        }        void activeStateChanged(boolean newActive) {            if (newActive == mActive) {                return;            }            // immediately set active state,             //so we'd never dispatch anything to inactive owner            //立即设置活动状态,因此我们永远不会向非活动所有者发送任何内容            mActive = newActive;            boolean wasInactive = LiveData.this.mActiveCount == 0;            LiveData.this.mActiveCount += mActive ? 1 : -1;            if (wasInactive && mActive) {                onActive();// 当Activity/Fragment为活跃状态时回调onActive()            }            if (LiveData.this.mActiveCount == 0 && !mActive) {                onInactive(); // 当Activity/Fragment未活跃状态时回调onInactive()            }            if (mActive) {                dispatchingValue(this);            }        }    }class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {        @NonNull final LifecycleOwner mOwner;        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer observer) {            super(observer);// 调用父类ObserverWrapper的构造函数传递Owner            mOwner = owner;        }        @Override        boolean shouldBeActive() {            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);        }        @Override        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {        // 实现GenericLifecycleObserver 当生命周期改变时回调onStateChanged            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {                removeObserver(mObserver);// DESTROYED时移除观察者                return;            }            activeStateChanged(shouldBeActive());        }        @Override        boolean isAttachedTo(LifecycleOwner owner) {            return mOwner == owner;        }        @Override        void detachObserver() {            mOwner.getLifecycle().removeObserver(this);        }    }   
  • ObserverWrapper 在Owner活跃状态改变时回调onActive和onInactive方法
  • LifecycleBoundObserver主要利用Lifecycler的生命周期观察者GenericLifecycleObserver,当设置了owner.getLifecycle().addObserver(wrapper)后,当生命周期改变时会回调onStateChange()方法,在生命周期为Destroy时移除Observer

setValue(T value) (主线程)

@MainThread    protected void setValue(T value) {        assertMainThread("setValue");//检测是否在主线程        mVersion++;        mData = value;        dispatchingValue(null);    }... private void dispatchingValue(@Nullable ObserverWrapper initiator) {        if (mDispatchingValue) {            mDispatchInvalidated = true;            return;        }        mDispatchingValue = true;        do {            mDispatchInvalidated = false;            if (initiator != null) {                considerNotify(initiator);                initiator = null;            } else {          //遍历mObservers中所有的Observer,调用considerNotify()更新数据                for (Iterator, ObserverWrapper>> iterator =                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {                    considerNotify(iterator.next().getValue());                    if (mDispatchInvalidated) {                        break;                    }                }            }        } while (mDispatchInvalidated);        mDispatchingValue = false;    }...private void considerNotify(ObserverWrapper observer) {        if (!observer.mActive) {            return;        }        if (!observer.shouldBeActive()) {            observer.activeStateChanged(false);            return;        }        if (observer.mLastVersion >= mVersion) {            return;        }        observer.mLastVersion = mVersion;        //更新数据 通过接口回调        observer.mObserver.onChanged((T) mData);    }...public interface Observer {    void onChanged(@Nullable T t);}...@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)public class DefaultTaskExecutor extends TaskExecutor {    private final Object mLock = new Object();    private ExecutorService mDiskIO = Executors.newFixedThreadPool(2);    @Nullable    private volatile Handler mMainHandler;    @Override    public void executeOnDiskIO(Runnable runnable) {        mDiskIO.execute(runnable);    }    @Override    public void postToMainThread(Runnable runnable) {     //子线程向主线程发消息        if (mMainHandler == null) {            synchronized (mLock) {                if (mMainHandler == null) {                    mMainHandler = new Handler(Looper.getMainLooper());                }            }        }        //noinspection ConstantConditions        mMainHandler.post(runnable);    }    @Override    public boolean isMainThread() {//检测是否在主线程具体实现        return Looper.getMainLooper().getThread() == Thread.currentThread();    }
  • setValue()中先检查是否主线程然后调用了dispatchingValue(),在dispatchingValue中遍历mObservers中所有的Observer,调用considerNotify()中.mObserver.onChanged(T)更新数据
    postValue(T value)(子线程)
 protected void postValue(T value) {        boolean postTask;        synchronized (mDataLock) {            postTask = mPendingData == NOT_SET;            mPendingData = value;        }        if (!postTask) {            return;        }        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);    }...  private final Runnable mPostValueRunnable = new Runnable() {        @Override        public void run() {            Object newValue;            synchronized (mDataLock) {                newValue = mPendingData;                mPendingData = NOT_SET;            }            //noinspection unchecked            setValue((T) newValue);        }    };
  • postValue()中传递的Runnable 也是调用setValue() 只不过是通过handle在子线程向主线程发消息

5.展望

本次分享只是分析了ViewModel,LiveData 的大概源码,与简单示例,但其实在实际生产环境中,我们需要使用ViewModel与Repository连接网络层,同时如果需要数据持久化还需要连接Room数据库层,通过ViewModel生成LiveData,UI层订阅LiveData,真正的实现数据驱动界面

再看一次架构图

更多相关文章

  1. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
  2. 一句话锁定MySQL数据占用元凶
  3. Android之TextureView浅析
  4. 在Android中创建启动界面
  5. Android项目创建和项目目录图解
  6. android中的application
  7. 已解决:Android向SD卡存储数据时出现java.io.FileNotFoundExcepti
  8. Android(安卓)Studio创建Xposed Module项目的正确姿势。
  9. 笔记-系统源码常用的Content Provider

随机推荐

  1. Android(安卓)Studio “Cannot create di
  2. android 运用百度地图画轨迹
  3. Android编译问题
  4. 广播机制 笔记
  5. adb使用wifi无线连接调试Android设备
  6. Android(安卓)图片添加水印
  7. HttpURLconnection上传数据
  8. Android(安卓)socket通信app Client端
  9. 调用getChildFragmentManager时出现的Bug
  10. Android编译环境搭建