Lifecycle、LiveData、ViewModel介绍

在 Android 框架中定义的大多数应用组件都存在生命周期。生命周期由操作系统或进程中运行的框架代码管理。它们是 Android 运作方式的核心,应用必须遵循它们。如果不这样做,可能会引发内存泄露甚至应用崩溃。

  • Lifecycle

(Lifecycle)生命周期感知型组件可执行操作来响应另一个组件(如 Activity 和 Fragment)的生命周期状态的变化。这些组件有助于您写出更有条理且往往更精简的代码,这样的代码更易于维护。

androidx.lifecycle 软件包提供了可用于构建生命周期感知型组件的类和接口 - 这些组件可以根据 Activity 或 Fragment 的当前生命周期状态自动调整其行为。

  • Lifecycle产生的原因

在真实的应用中,最终会有太多管理界面和其他组件的调用,以响应生命周期的当前状态。管理多个组件会在生命周期方法(如 onStart() 和 onStop())中放置大量的代码,这使得它们难以维护。

此外,无法保证组件会在 Activity 或 Fragment 停止之前启动。在我们需要执行长时间运行的操作(如 onStart() 中的某种配置检查)时尤其如此。这可能会导致出现一种竞争条件,在这种条件下,onStop() 方法会在 onStart() 之前结束,这使得组件留存的时间比所需的时间要长。

androidx.lifecycle 软件包提供的类和接口可帮助您以弹性和隔离的方式解决这些问题。

1.Lifecycle

1.1Lifecycle关键类说明

  • Lifecycle

定义一个有Android生命周期的对象,是一个类,用于存储有关组件(如 Activity 或 Fragment)的生命周期状态的信息,并允许其他对象观察此状态。

使用两种主要枚举跟踪其关联组件的生命周期状态:

事件:从框架和 Lifecycle 类分派的生命周期事件。这些事件映射到 Activity 和 Fragment 中的回调事件。

  public enum Event {//生命周期方法ON_CREATE,ON_START,ON_RESUME,ON_PAUSE,ON_STOP,ON_DESTROY,//注解以后所有生命周期方法都会回调ON_ANY}

状态:由 Lifecycle 对象跟踪的组件的当前状态。

public enum State {DESTROYED,INITIALIZED,CREATED,STARTED,RESUMED;public boolean isAtLeast(@NonNull State state) {return compareTo(state) >= 0;}}

构成 Android Activity 生命周期的状态和事件如图:

您可以将状态看作图中的节点,将事件看作这些节点之间的边。

  • LifecycleOwner

LifecycleOwner 是单一方法接口,表示类持有 Lifecycle。它具有一种方法(即 getLifecycle()),该方法必须由类实现。

此接口从各个类(如 Fragment 和 AppCompatActivity)抽象化 Lifecycle 的所有权,并允许编写与这些类搭配使用的组件。任何自定义应用类均可实现 LifecycleOwner 接口。

  • LifecycleObserver

标记一个类作为LifecycleObserver,生命周期观察者回调,LifecycleObserver没有任何方法,依赖OnLifecycleEvent注解方法标示监听生命周期方法;

  • LifecycleRegistry

实现Lifecycle接口,可以同时通知多个LifecycleObserver观察者对象;

注意:实现 LifecycleObserver 的组件可与实现 LifecycleOwner 的组件无缝协同工作,因为所有者可以提供生命周期,而观察者可以注册以观察生命周期。

1.2Lifecycle使用示例(Activity继承AppCompatActivity)

1.2.1引入依赖

在 根目录 的build.gradle文件中,加上google()的远程仓库声明(现在AS创建的工程已经默认包含了该声明)。

allprojects {repositories {jcenter()//加上这一句。google()}
}

添加Lifecycle依赖有如下两种方式

implementation 'com.android.support:appcompat-v7:28.0.0'

或者

  • 选择仅导入LiveDataViewModelLifecycles的其中一种,或者全部导入。
  • 注解处理器,在Java8上使用common-java8,在Java8以下使用compiler
  • 流式处理支持库reactivestreams
  • 测试支持库core-testing
    def lifecycle_version = "1.1.1"// ViewModel and LiveDataimplementation "android.arch.lifecycle:extensions:$lifecycle_version"// alternatively - just ViewModelimplementation "android.arch.lifecycle:viewmodel:$lifecycle_version" // For Kotlin use viewmodel-ktx// alternatively - just LiveDataimplementation "android.arch.lifecycle:livedata:$lifecycle_version"// alternatively - Lifecycles only (no ViewModel or LiveData).//     Support library depends on this lightweight importimplementation "android.arch.lifecycle:runtime:$lifecycle_version"annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version" // For Kotlin use kapt instead of annotationProcessor// alternately - if using Java8, use the following instead of compilerimplementation "android.arch.lifecycle:common-java8:$lifecycle_version"// optional - ReactiveStreams support for LiveDataimplementation "android.arch.lifecycle:reactivestreams:$lifecycle_version"// optional - Test helpers for LiveDatatestImplementation "android.arch.core:core-testing:$lifecycle_version"

同步依赖以后:

com.android.support:appcompat-v7:28.0.0会把支持的依赖库全部添加,默认会把lifecycle相关库添加,也可以单独指定添加每个依赖库;

1.2.2定义生命周期观察者

1)实现观察者接口LifecycleObserver接口;

2)在要监听相应的生命周期方法添加注解;

@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
 public void onCreate(){}

3)在相应的生命周期方法书写业务逻辑;

public class LiveObserver implements LifecycleObserver {private static final  String TAG = LiveObserver.class.getSimpleName();@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)public void onCreate(){Log.d(TAG, "onCreate");}@OnLifecycleEvent(Lifecycle.Event.ON_START)public void onStart(){Log.d(TAG, "onStart");}@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)public void onResume(){Log.d(TAG, "onResume");}@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)public void onPause(){Log.d(TAG, "onPause");}@OnLifecycleEvent(Lifecycle.Event.ON_STOP)public void onStop(){Log.d(TAG, "onStop");}@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)public void onDestroy(){Log.d(TAG, "onDestroy");}
}

1.2.3添加生命周期观察者监听生命周期方法回调

public class MainActivity extends AppCompatActivity {private LiveObserver liveObserver;  private Button add;private Button remove;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);init();}public void init(){add = findViewById(R.id.add);remove  = findViewById(R.id.remove);add.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if(liveObserver == null){liveObserver  = new LiveObserver();getLifecycle().addObserver(liveObserver);}}});remove.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if(liveObserver != null){getLifecycle().removeObserver(liveObserver);liveObserver = null;}}});}
}

点击按钮添加生命周期回调方法观察者:

getLifecycle().addObserver(liveObserver);

点击按钮移除生命周期回调方法观察者:

getLifecycle().removeObserver(liveObserver);

  • 点击按钮添加生命周期回调方法观察者

通过日志输出查看观察者的生命周期回调

Home键进入后台

11-06 09:29:48.411 3524-3524/com.baidu.baike.newcomponents D/LiveObserver: onPause
11-06 09:29:48.774 3524-3524/com.baidu.baike.newcomponents D/LiveObserver: onStop

APP回调前台

11-06 09:29:38.438 3524-3524/com.baidu.baike.newcomponents D/LiveObserver: onStart
11-06 09:29:38.438 3524-3524/com.baidu.baike.newcomponents D/LiveObserver: onResume

关闭Activity页面

11-06 09:50:36.688 3524-3524/com.baidu.baike.newcomponents D/LiveObserver: onPause
11-06 09:50:37.030 3524-3524/com.baidu.baike.newcomponents D/LiveObserver: onStop
11-06 09:50:37.031 3524-3524/com.baidu.baike.newcomponents D/LiveObserver: onDestroy

启动Activity页面

11-06 09:51:36.623 3524-3524/com.baidu.baike.newcomponents D/LiveObserver: onCreate
11-06 09:51:36.623 3524-3524/com.baidu.baike.newcomponents D/LiveObserver: onStart
11-06 09:51:36.623 3524-3524/com.baidu.baike.newcomponents D/LiveObserver: onResume

其他操作可以自己尝试查看生命周期观察者回调;

  • 点击按钮移除生命周期回调方法观察者

不再监听生命周期变化,无生命周期观察者回调日志;

  • 测试结果说明:

1)在 第一次绑定 的时候,LifeObserver会从onCreate()方法依次回调到Activity当前所处的生命周期状态。

2)解绑 不会触发任何生命周期回调,之后也收不到Activity的任何通知。

3)在绑定过后,LifeObserver会跟随着Activity的生命周期变化。

1.3Lifecycle使用示例(Activity继承Activity)

继承Activity实现LifecycleOwner接口;

参考SupportActivity源码查看怎么创建返回的Lifecycle,实例化LifecycleRegistry,LifecycleRegistry实现了Lifecycle;

/*** 自定义实现LifecycleOwner*/
public class LifeCycleActivity extends Activity implements LifecycleOwner{//创建 mLifecycleRegistry 对象,其构造函数为实现了 LifecycleOwner 的对象。private LifecycleRegistry mLifecycleRegistry= new LifecycleRegistry(this);//生命周期观察者private LiveObserver liveObserver;private Button add;private Button remove;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);init();}public void init(){add = findViewById(R.id.add);remove  = findViewById(R.id.remove);add.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if(liveObserver == null){liveObserver  = new LiveObserver();getLifecycle().addObserver(liveObserver);}}});remove.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if(liveObserver != null){getLifecycle().removeObserver(liveObserver);liveObserver = null;}}});}@CallSuperprotected void onSaveInstanceState(Bundle outState) {this.mLifecycleRegistry.markState(Lifecycle.State.CREATED);super.onSaveInstanceState(outState);}@NonNull@Overridepublic Lifecycle getLifecycle() {return this.mLifecycleRegistry;}
}

可以参考上面测试方式查看日志输出,测试输出结果和1.2.3添加生命周期观察者监听生命周期方法回调一样;

1.4Lifecycle实现原理(AppCompatActivity)

我会发现为什么继承Activity需要实现LifecycleOwner,而继承android.support.v7.app.AppCompatActivity/android.support.v4.app.Fragment类不需要单独实现LifecycleOwner接口;

android.support.v7.app.AppCompatActivity

AppCompatActivity继承自SupportActivitypublic class SupportActivity extends Activity implements LifecycleOwner, Component {private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);public Lifecycle getLifecycle() {return this.mLifecycleRegistry;}
}

android.support.v4.app.Fragment

public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner, ViewModelStoreOwner {LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);public Lifecycle getLifecycle() {return this.mLifecycleRegistry;}
}

发现AppCompatActivity/Fragment都已经实现了LifecycleOwner接口,不需要我们自己实现;

1.4.1如何实现生命周期回调给生命周期观察者

通过代码查看SupportActivity类在onCreate()添加了没有界面ReportFragment;

public class SupportActivity extends Activity implements LifecycleOwner, Component {protected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);ReportFragment.injectIfNeededIn(this);}
}

添加没有页面ReportFragment的的目的是什么呢?

ReportFragment属于SupportActivity页面的一部分,当SupportActivity生命周期发生变化时,ReportFragment生命周期也会随着变化;

看下ReportFragment生命周期方法变化时,会做哪些处理?

public class ReportFragment extends Fragment {@Overridepublic void onStart() {super.onStart();dispatchStart(mProcessListener);dispatch(Lifecycle.Event.ON_START);}private void dispatch(Lifecycle.Event event) {Activity activity = getActivity();if (activity instanceof LifecycleRegistryOwner) {((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);return;}if (activity instanceof LifecycleOwner) {Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();if (lifecycle instanceof LifecycleRegistry) {((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);}}}
}

ReportFragment生命周期回调方法调用dispatch(Lifecycle.Event.ON_START)方法,传递相应的生命周期事件;

调用LifecycleRegistry实例的handleLifecycleEvent(event)方法;

((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);

public class LifecycleRegistry extends Lifecycle {//设置当前对的状态并且通知生命周期观察者//注意:当前状态和最后一次调用的状态一样,则不通知生命周期观察者public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {State next = getStateAfter(event);moveToState(next);}private void moveToState(State next) {if (mState == next) {return;}mState = next;if (mHandlingEvent || mAddingObserverCounter != 0) {mNewEventOccurred = true;// we will figure out what to do on upper level.return;}mHandlingEvent = true;sync();mHandlingEvent = false;}private void forwardPass(LifecycleOwner lifecycleOwner) {Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =mObserverMap.iteratorWithAdditions();while (ascendingIterator.hasNext() && !mNewEventOccurred) {Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();ObserverWithState observer = entry.getValue();while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred&& mObserverMap.contains(entry.getKey()))) {pushParentState(observer.mState);observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));popParentState();}}}private void backwardPass(LifecycleOwner lifecycleOwner) {Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator =mObserverMap.descendingIterator();while (descendingIterator.hasNext() && !mNewEventOccurred) {Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();ObserverWithState observer = entry.getValue();while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred&& mObserverMap.contains(entry.getKey()))) {Event event = downEvent(observer.mState);pushParentState(getStateAfter(event));observer.dispatchEvent(lifecycleOwner, event);popParentState();}}}// happens only on the top of stack (never in reentrance),// so it doesn't have to take in account parentsprivate void sync() {LifecycleOwner lifecycleOwner = mLifecycleOwner.get();if (lifecycleOwner == null) {Log.w(LOG_TAG, "LifecycleOwner is garbage collected, you shouldn't try dispatch "+ "new events from it.");return;}while (!isSynced()) {mNewEventOccurred = false;// no need to check eldest for nullability, because isSynced does it for us.if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {//向后移动,例如当前StARTED状态锁屏操作暂停界面backwardPass(lifecycleOwner);}Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();if (!mNewEventOccurred && newest != null&& mState.compareTo(newest.getValue().mState) > 0) {//向前移动,例如当前锁屏,重新打开屏幕,属于向前移动forwardPass(lifecycleOwner);}}mNewEventOccurred = false;}
}

根据生命周期发生的前后顺序决定如何通知生命周期观察者:

//向后移动,例如当前StARTED状态锁屏操作暂停界面

backwardPass(lifecycleOwner);

//向前移动,例如当前锁屏,重新打开屏幕,属于向前移动

forwardPass(lifecycleOwner);

真正派发生命周期回调给观察者

observer.dispatchEvent(lifecycleOwner, event);

整体的生命周期回调方法监听顺序:

通过断点调试代码查看如何将生命周期回调给观察者(onStart):

1.5Lifecycle实现原理(Fragment)

通过代码可以发现android.support.v4.app.Fragment可以发现Fragment已经实现LifecycleOwner接口,使用原理和1.3Lifecycle实现原理(AppCompatActivity)类似;

public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner, ViewModelStoreOwner {LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);public Lifecycle getLifecycle() {return this.mLifecycleRegistry;}void performStop() {this.mLifecycleRegistry.handleLifecycleEvent(Event.ON_STOP);}
}

参考:

使用生命周期感知型组件处理生命周期

https://developer.android.google.cn/topic/libraries/architecture/lifecycle

https://www.jianshu.com/p/ee6b81b9777a

Lifecycle 版本说明

https://developer.android.google.cn/jetpack/androidx/releases/lifecycle#declaring_dependencies

Lifecycle、LiveData、ViewModel讲解之Lifecycle相关推荐

  1. Lifecycle LiveData LiveData LiveData

    0001Lifecycle 原文:http://shymanzhu.com/2017/12/02/Android%20架构组件%EF%BC%88一%EF%BC%89--Lifecycle-Aware% ...

  2. LiveData ViewModel 使用详解

    什么是 LiveData LiveData 是一个可观测的数据持有类,但是不同于通常的被观察者,LiveData 具有生命周期感知能力.通俗点说,LiveData 就是具有 "Live&qu ...

  3. android lifecycle,Android 架构组件之 LifeCycle详解

    1.Lifecycle介绍 为什么要使用lifecycle? activity 和fragment 是有声明周期的,有时候,我们的很多操作需要写在声明周期的方法中,比如,下载,文件操作等,这样很多情况 ...

  4. android DataBind LiveData ViewModel 使用详解

    1.导入android x ,升级 版本到28 implementation 'androidx.appcompat:appcompat:1.0.0'def room_version = " ...

  5. Andriod --- JetPack (五):DataBinding + LiveData +ViewModel 简单实例

    1.Andriod - JetPack (一):初识 JetPack 2.Andriod - JetPack (二):LifeCycle 的诞生 3.Andriod - JetPack (三):Vie ...

  6. Android架构组件LiveData+ViewModel

    前言 最近项目中有用到LiveData+ViewModel的架构组件,今天来学习一波.本篇文章参考:MVVM 架构,ViewModel和LiveData 所有语言为Kotlin. LiveData L ...

  7. LiveData + ViewModel + Room (Google 官文)+Demo

    原文地址:lovestack.github.io/2017/11/13/- demo:github.com/lovestack/V- 本指南适用于那些过去构建应用程序有基础知识,现在想知道构建强大的生 ...

  8. room+livedata+ViewModel+RecyclerView

    1 简介 1.1 room android 官方推荐的数据库框架,room主要包含三个组件:roomDatabase,entity,Dao.    使用 Room 数据库来获取与该数据库关联的数据访问 ...

  9. Jetpack之ViewModel讲解

    [1]关于ViewModel ViewModel是Jetpack AAC的重要组件,同时也有一个同名抽象类. ViewModel,意为 视图模型,即为界面准备数据的模型.简单理解就是,ViewMode ...

最新文章

  1. [转]C#算法 一对小兔子一年后长成大兔子;一对大兔子每半年生一对小兔子。大兔子的繁殖期为4年,兔子的寿命是6年。假定第一年年初投放了一对小兔子,试编程计算,第n年末总共会有多少对兔子...
  2. SAP 电商云 Accelerator 和 Spartacus UI 的工作机制差异
  3. 被同事嘲笑说技术方案没深度?
  4. 数据结构数组计算机中的应用,2018考研计算机:数据结构数组和广义表复习重点...
  5. 脑洞大开的插画师,每幅都戳到我诡异的笑点
  6. Webstorm相关设置
  7. matlab 复频谱图,基于MATLAB实现连续信号与系统复频域分析
  8. “”和“”的你真的理解吗?
  9. 清风数学建模学习笔记——TOPSIS法(优劣解距离法)
  10. 自己动手写2D物理引擎-初级篇(1)
  11. 数学建模之传染病SIR模型(新冠真实数据)
  12. 《东周列国志》第十二回 卫宣公筑台纳媳 高渠弥乘间易君
  13. numpy向量化函数
  14. pandas之数据合并
  15. 重庆大学计算机信息管理基础2013,重庆大学计算机信息管理基础课程考试试卷B.doc...
  16. Windows11系统闪屏解决方案
  17. 退出计算机用户的快捷方式,如何注销计算机或从Windows 10注销
  18. rviz进行kitti数据集可视化时加载小车模型报错
  19. 函数参数*arg和参数**arg区别
  20. Java日期时间的设置问题

热门文章

  1. 【Android -- RxJava】RxJava2.0 教程(七),如何使用 Flowable
  2. 2018第一作,JFDF快速开发框架的横空出世
  3. 团队项目:过山车游戏 NABC
  4. Echarts柱状图的宽度设置
  5. 测试行业的迅猛发展带来一些新的挑战和机遇,所以到底自动化测试怎么样呢?
  6. 从样本中抽样的Python技术
  7. CSA发布|《洞察2022 云上数据安全与重要事项 》
  8. springBoot配置文件设置mongodb连接密码加密
  9. 微信超好玩的“后羿射日”特效,赶紧试试!!
  10. 在高并发情况下如何解决用户超领优惠券问题