Lifecycle、LiveData、ViewModel讲解之Lifecycle
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'
或者
- 选择仅导入
LiveData
、ViewModel
、Lifecycles
的其中一种,或者全部导入。 - 注解处理器,在
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相关推荐
- Lifecycle LiveData LiveData LiveData
0001Lifecycle 原文:http://shymanzhu.com/2017/12/02/Android%20架构组件%EF%BC%88一%EF%BC%89--Lifecycle-Aware% ...
- LiveData ViewModel 使用详解
什么是 LiveData LiveData 是一个可观测的数据持有类,但是不同于通常的被观察者,LiveData 具有生命周期感知能力.通俗点说,LiveData 就是具有 "Live&qu ...
- android lifecycle,Android 架构组件之 LifeCycle详解
1.Lifecycle介绍 为什么要使用lifecycle? activity 和fragment 是有声明周期的,有时候,我们的很多操作需要写在声明周期的方法中,比如,下载,文件操作等,这样很多情况 ...
- android DataBind LiveData ViewModel 使用详解
1.导入android x ,升级 版本到28 implementation 'androidx.appcompat:appcompat:1.0.0'def room_version = " ...
- Andriod --- JetPack (五):DataBinding + LiveData +ViewModel 简单实例
1.Andriod - JetPack (一):初识 JetPack 2.Andriod - JetPack (二):LifeCycle 的诞生 3.Andriod - JetPack (三):Vie ...
- Android架构组件LiveData+ViewModel
前言 最近项目中有用到LiveData+ViewModel的架构组件,今天来学习一波.本篇文章参考:MVVM 架构,ViewModel和LiveData 所有语言为Kotlin. LiveData L ...
- LiveData + ViewModel + Room (Google 官文)+Demo
原文地址:lovestack.github.io/2017/11/13/- demo:github.com/lovestack/V- 本指南适用于那些过去构建应用程序有基础知识,现在想知道构建强大的生 ...
- room+livedata+ViewModel+RecyclerView
1 简介 1.1 room android 官方推荐的数据库框架,room主要包含三个组件:roomDatabase,entity,Dao. 使用 Room 数据库来获取与该数据库关联的数据访问 ...
- Jetpack之ViewModel讲解
[1]关于ViewModel ViewModel是Jetpack AAC的重要组件,同时也有一个同名抽象类. ViewModel,意为 视图模型,即为界面准备数据的模型.简单理解就是,ViewMode ...
最新文章
- [转]C#算法 一对小兔子一年后长成大兔子;一对大兔子每半年生一对小兔子。大兔子的繁殖期为4年,兔子的寿命是6年。假定第一年年初投放了一对小兔子,试编程计算,第n年末总共会有多少对兔子...
- SAP 电商云 Accelerator 和 Spartacus UI 的工作机制差异
- 被同事嘲笑说技术方案没深度?
- 数据结构数组计算机中的应用,2018考研计算机:数据结构数组和广义表复习重点...
- 脑洞大开的插画师,每幅都戳到我诡异的笑点
- Webstorm相关设置
- matlab 复频谱图,基于MATLAB实现连续信号与系统复频域分析
- “”和“”的你真的理解吗?
- 清风数学建模学习笔记——TOPSIS法(优劣解距离法)
- 自己动手写2D物理引擎-初级篇(1)
- 数学建模之传染病SIR模型(新冠真实数据)
- 《东周列国志》第十二回 卫宣公筑台纳媳 高渠弥乘间易君
- numpy向量化函数
- pandas之数据合并
- 重庆大学计算机信息管理基础2013,重庆大学计算机信息管理基础课程考试试卷B.doc...
- Windows11系统闪屏解决方案
- 退出计算机用户的快捷方式,如何注销计算机或从Windows 10注销
- rviz进行kitti数据集可视化时加载小车模型报错
- 函数参数*arg和参数**arg区别
- Java日期时间的设置问题