每个Android开发者都应该面对过生命周期问题,即操作系统启动、停止和销毁Activity。这意味着开发者需要根据生命周期的不同阶段,有针对性地管理组件状态,比如用于更新用户界面的可观察对象。生命周期管理(Lifecycles)帮助开发者创建“可感知生命周期的”组件,让其自己管理自己的生命周期,从而 减少内存泄露和崩溃的可能性。生命周期库是其他架构组件(如 LiveData)的基础。
在我们日常编码的过程中,必不可少的要与系统组件Activity/Fragment打交道,他们都是具有生命周期的组件,如何有效的管理这些组件的生命周期与业务逻辑更好的交互,成为了开发中一个重要的关注点。比如目前比较常用的MVP编码架构,我们的业务逻辑Presenter层需要感知View层(Activity/Fragment)生命周期的变化,从而做出相应的业务处理。如下代码所示,我模拟写一个简单的MVP模板代码。
Presenter层样式代码
public class LoginPresenter {
/**
* 用户登录
*
* @param userName
* @param userPwd
*/
public void login(String userName, String userPwd) {
//执行登录逻辑...
}
/**
* Activity创建时执行相关逻辑
*/
public void onCreate() {
// 1.初始化操作
// 2.初始化Model层
// 3.绑定View层
...
}
// Activity call onStart()
public void onStart() {
...
}
// Activity call onResume()
public void onResume() {
...
}
// Activity call onPause()
public void onPause() {
...
}
// Activity call onStop()
public void onStop() {
...
}
/**
* Activity销毁时执行相关逻辑
*/
public void onDestroy() {
// 1.解绑View层
// 2.取消订阅关系
// 3.取消网络请求
// 4.释放资源
...
}
}
View层样式代码
public class MainActivity extends AppCompatActivity {
private LoginPresenter mLoginPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLoginPresenter = new LoginPresenter();
mLoginPresenter.onCreate();
}
@Override
protected void onStart() {
super.onStart();
mLoginPresenter.onStart();
}
@Override
protected void onResume() {
super.onResume();
mLoginPresenter.onResume();
}
@Override
protected void onPause() {
super.onPause();
mLoginPresenter.onPause();
}
@Override
protected void onStop() {
super.onStop();
mLoginPresenter.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
mLoginPresenter.onDestroy();
}
}
实际生产环境中,Presenter层可能不会感知那么多的生命周期变化,但是随着业务的复杂,Activity/Fragment中生命周期管理代码也会非常的复杂,最终有太多的调用导致相关生命周期方法变得十分臃肿,并且都是我们手动的管理。那么这时候我们希望Presenter层能够自动的感知Activity/Fragment生命周期变化,从而做出相应的逻辑处理,如果这样那该多好。这时候Android官方架构组件Lifecycle就可以帮助我们实现这一需求。
Project build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
App build.gradle
dependencies {
...
implementation "android.arch.lifecycle:runtime:1.1.1"
annotationProcessor "android.arch.lifecycle:compiler:1.1.1"
}
貌似SDK 26以上新建项目会自动引入
这时候我们对上面的LoginPresenter修改如下:
public class LoginPresenter implements LifecycleObserver{
/**
* 用户登录
*
* @param userName
* @param userPwd
*/
public void login(String userName, String userPwd) {
//执行登录逻辑...
}
/**
* Activity创建时执行相关逻辑
*/
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void onCreate() {
// 1.初始化操作
// 2.初始化Model层
// 3.绑定View层
...
}
// Activity call onStart()
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() {
...
}
// Activity call onResume()
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
...
}
// Activity call onPause()
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause() {
...
}
// Activity call onStop()
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop() {
...
}
/**
* Activity销毁时执行相关逻辑
*/
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestroy() {
// 1.解绑View层
// 2.取消订阅关系
// 3.取消网络请求
// 4.释放资源
...
}
// match all event
@OnLifecycleEvent(Lifecycle.Event.ON_ANY)
void onLifecycleChanged(){
}
}
然后修改MainActivity代码如下
将LoginPresenter作为观察者添加到Lifecycle中
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLoginPresenter = new LoginPresenter();
mLoginPresenter.onCreate();
//添加observer
getLifecycle().addObserver(mLoginPresenter);
}
...
如此,每当Activity发生了对应的生命周期改变,Presenter就会执行对应事件注解的方法,此外除了笔者刚才写的通过Presenter实现LifecycleObserver,然后为各个生命周期条件相应的注解,还有一种方式是实现官方提供的DefaultLifeObserver接口,不过要在build.gradle中添加如下依赖
implementation 'android.arch.lifecycle:common-java8:1.1.1'
然后修改我们的LoginPresenter
public class LoginPresenter implements DefaultLifecycleObserver{
/**
* 用户登录
*
* @param userName
* @param userPwd
*/
public void login(String userName, String userPwd) {
//执行登录逻辑...
}
/**
* Activity创建时执行相关逻辑
*/
public void onCreate(@NonNull LifecycleOwner owner) {
// 1.初始化操作
// 2.初始化Model层
// 3.绑定View层
...
}
// Activity call onStart()
public void onStart(@NonNull LifecycleOwner owner) {
...
}
// Activity call onResume()
public void onResume(@NonNull LifecycleOwner owner) {
...
}
// Activity call onPause()
public void onPause(@NonNull LifecycleOwner owner) {
...
}
// Activity call onStop()
public void onStop(@NonNull LifecycleOwner owner) {
...
}
/**
* Activity销毁时执行相关逻辑
*/
public void onDestroy(@NonNull LifecycleOwner owner) {
// 1.解绑View层
// 2.取消订阅关系
// 3.取消网络请求
// 4.释放资源
...
}
}
DefaultLifeObserver源码:
其实DefaultLifeObserver内部已经帮我们实现了这些生命周期方法,并且利用到了JDK1.8的新特性,在接口中定义默认方法 通过default修饰符
public interface DefaultLifecycleObserver extends FullLifecycleObserver {
@Override
default void onCreate(@NonNull LifecycleOwner owner) {
}
@Override
default void onStart(@NonNull LifecycleOwner owner) {
}
@Override
default void onResume(@NonNull LifecycleOwner owner) {
}
@Override
default void onPause(@NonNull LifecycleOwner owner) {
}
@Override
default void onStop(@NonNull LifecycleOwner owner) {
}
@Override
default void onDestroy(@NonNull LifecycleOwner owner) {
}
}
两者的取舍:
Google官方更推荐我们使用DefaultLifecycleObserver类,并声明一旦Java8成为Android的主流,注释将被弃用,所以介于DefaultLifecycleObserver和注解两者之间,更推荐使用DefaultLifecycleObserver 。
LifecycleObserver接口(Lifecycle观察者):实现该接口的类,通过注解的方式,可以通过被LifecycleOwner类的addObserver(LifecycleObserver observer)方法注册,被注册后,LifecycleObserver便可以观察到LifecycleOwner的生命周期事件。
LifecycleOwner接口(Lifecycle持有者):实现该接口的类持有生命周期(Lifecycle对象),该接口的生命周期(Lifecycle对象)的改变会被其注册的观察者LifecycleObserver观察到并触发其对应的事件。
Lifecycle(生命周期):和LifecycleOwner不同的是,LifecycleOwner本身持有Lifecycle对象,LifecycleOwner通过其Lifecycle getLifecycle()的接口获取内部Lifecycle对象。
State(当前生命周期所处状态):如图所示。
Event(当前生命周期改变对应的事件):如图所示,当Lifecycle发生改变,如进入onCreate,会自动发出ON_CREATE事件。
以V4包Fragment 查看LifecycleOwner、LifecycleObserver、Lifecycle关系
public interface LifecycleOwner {
@NonNull
Lifecycle getLifecycle();
}
//默认最新的SDK版本SupportActivity、Fragment都已经实现了LifecycleOwner如下
public class Fragment extends Activity implements LifecycleOwner {
...
private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
...
}
//我们也可以实现一个自定义的LifecycleOwner
public class MyActivity extends Activity implements LifecycleOwner {
private LifecycleRegistry mLifecycleRegistry;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLifecycleRegistry = new LifecycleRegistry(this);
mLifecycleRegistry.markState(Lifecycle.State.CREATED);
}
@Override
public void onStart() {
super.onStart();
mLifecycleRegistry.markState(Lifecycle.State.STARTED);
}
@NonNull
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
}
public abstract class Lifecycle {
public abstract void addObserver(@NonNull LifecycleObserver observer);
public abstract void removeObserver(@NonNull LifecycleObserver observer);
}
public interface LifecycleObserver {
}
public class LifecycleRegistry extends Lifecycle {
}
public void markState(@NonNull State state) {
moveToState(state);
}
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 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) {
backwardPass(lifecycleOwner);
}
Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
if (!mNewEventOccurred && newest != null
&& mState.compareTo(newest.getValue().mState) > 0) {
forwardPass(lifecycleOwner);
}
}
mNewEventOccurred = 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();
}
}
}
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
保持 UI 控制器(Activity和Fragment)尽可能的精简。它们不应该试图去获取它们所需的数据;相反,要用 ViewModel来获取,并且观察LiveData将数据变化反映到视图中。
尝试编写数据驱动(data-driven)的UI,即UI控制器的责任是在数据改变时更新视图或者将用户的操作通知给 ViewModel。
将数据逻辑放到 ViewModel类中。ViewModel应该作为UI控制器和应用程序其它部分的连接服务。注意:不是由 ViewModel 负责获取数据(例如:从网络获取)。相反,ViewModel 调用相应的组件获取数据,然后将数据获取结果提供给 UI 控制器。
使用Data Binding来保持视图和UI控制器之间的接口干净。这样可以让视图更具声明性,并且尽可能减少在 Activity 和 Fragment 中编写更新代码。如果你喜欢在 Java 中执行该操作,请使用像Butter Knife 这样的库来避免使用样板代码并进行更好的抽象化。
如果 UI 很复杂,可以考虑创建一个Presenter类来处理UI的修改。虽然通常这样做不是必要的,但可能会让 UI 更容易测试。
不要在 ViewModel 中引用View或者 Activity的 context。因为如果ViewModel存活的比 Activity 时间长(在配置更改的情况下),Activity 将会被泄漏并且无法被正确的回收。
其实总结下来,Lifecycle组件核心就是一个观察者模式
回想我们的观察者模式中两个角色
1.抽象主题 2.抽象观察者
那么抽象主题具备增加观察者和移除观察者的方法,同时还具备一个容器保存所有的观察者,还具备一个主题发生变化通知观察者的方法从而使观察者做出相应的响应
那么这里我们可以采用类比方式
我们可以把实现了LifecycleObserver接口的元素称为观察者
把Lifecycle称为抽象主题,LifecycleRegistry其实就是主题的具体实现啦。
有了这两个核心元素之后,我们怎么实现Presenter感知View组件(Activity/Fragment)生命周期变化呢
那么此时我们的Presenter实现了LifecycleObserver,他就作为了一个观察者,我们的Activity/Fragement实现了LifecycleOwner接口,那么他就具备了getLifecycle()方法,同时Activity/Fragment也具体实现了,通过new LifecycleRegistry() 生成了一个具体的主题LifecycleRegistry。
那么这时候观察者有了,抽象主题也有了,怎么触发主题变化,然后通知到每个观察者呢。首先我们在Activity/Fragment中通过手动的调用getLifecycle().addObserver(LifecycleObserver observer)将Presenter作为观察者添加到主题的容器中。此时查看源码我们可以发现。通过Activity/Fragment会在生命周期方法的回调中主动的标记状态,从而触发主题LifecycleRegistry发生变化,从而通知到每个观察者从而就实现了Presenter可以感知到Activity/Fragment生命周期变化