Lifecycle实现浅析

744 阅读10分钟

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

Google官方在2018年的I/O大会上正式推出JetPack组件,作为关于Android应用程序构架设计的标准。Lifecycle是最早亮相的组件之一,提供了可以用于构建生命周期感知组件的类和接口,而常用的两大JetPack成员LiveData和ViewModel也与此略有联系。

生命周期感知能力

Lifecycle提供了用于构造生命周期感知组件的类和接口,也就是让自定义组件具有了生命周期感知能力,那为什么这样做以及如何做到呢?

1.为什么要考虑生命周期

我们从两个角度考虑这个问题。

从需求层面:用户在生命周期活跃的时候使用某个功能,同样也想在生命周期死亡的时候结束某个功能。

从性能层面:大家都知道内存泄漏是因为长生命周期的对象持有短生命周期的对象引用而导致内存不能及时回收的现象,如果存在大量这种本该回收而不能回收的对象,很快就会OOM。

2.解决的思路

既然短生命周期的对象不能及时释放从而造成内存泄漏,那我们只要在对应的生命周期进行分配和释放资源就可以解决问题。这里定义一个播放资源类,里面含有开始播放和停止播放两个功能,在Activity的start、pause生命周期里进行调用,伪代码如下:

public class MainActivity extends AppCompatActivity {

    private final String activityTag = getClass().getName();
    //伪播放资源
    private MusicService musicService = new MusicService();
    @Override
    protected void onStart() {
        super.onStart();
        musicService.playMusic();
        Log.e(activityTag, "playMusic");
    }

    @Override
    protected void onPause() {
        super.onPause();
        musicService.stopMusic();
        Log.e(activityTag, "stopMusic");
    }

}
3.Lifecycle更为优雅的实现

上面的方案可以在相应的生命周期进行资源的管理,但是试想如果每个activity都需要显式声明资源类,以及需要在对应的生命周期进行资源管理,样板代码不仅多且杂乱。因此Google推出了Lifecycle组件,可以在对应功能上追踪生命周期而取消样板代码。伪代码如下:

public class MusicService implements LifecycleObserver {
    private final String activityTag = getClass().getName();

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void playMusic(){
        Log.e(activityTag, "playMusic");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void stopMusic(){
        Log.e(activityTag, "stopMusic");
    }
}
public class MainActivity extends AppCompatActivity {
    
    private MusicService musicService;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }
    
    private void init(){
        musicService = new MusicService();
        getLifecycle().addObserver(musicService);
    }
    
}

可以看到之前的实现变成了让播放资源类继承LifecycleObserver接口,然后在对应功能上进行Lifecycle.Event事件的注释,然后在对应的Activity类中调用getLifecycle().addObserver方法绑定实现了接口的资源类。之前需要在各个生命周期进行处理的代码变成了一次绑定,自动响应,更加方便且属于官方支持。

Observer很容易就想到了观察者模式,只要我们在对应的生命周期进行事件订阅并且官方封装,自然省略了样板代码,事实也正是这样,Lifecycle组件就是通过这样的方式追踪生命周期,获得生命周期的感知能力。

Lifecycle实现细节

既然上面猜想到了观察者模式,这里我们围绕着几个类对接下来的内容进行展开。

Lifecycle:记录组件生命周期和信息的类,默认实现是LifecycleRegistry。

LifecycleOwner:实际的被观察者,继承LifecycleOwner接口获得被观察的能力,可以通过getLifecycle方法获得对应的Lifecycle对象。

LifecycleObserver:生命周期的观察者,可以被Lifecycle的addObserver进行注册,注册后可以监听被观察者的生命周期变化。

1.Lifecycle

之前提到Lifecycle是记录组件生命周期和信息的类,这是一个抽象类,里面只有两个抽象方法addObserver,removeObserver。除此之外,里面还有两个枚举类记录Event和State记录生命周期的状态,分别是:

public enum Event {
    /**
     * Constant for onCreate event of the {@link LifecycleOwner}.
     */
    ON_CREATE,
    ON_START,
    ON_RESUME,
    ON_PAUSE,
    ON_STOP,
    ON_DESTROY,
    ON_ANY
}
public enum State {
    /**
     * Destroyed state for a LifecycleOwner. After this event, this Lifecycle will not dispatch
     * any more events. For instance, for an {@link android.app.Activity}, this state is reached
     * <b>right before</b> Activity's {@link android.app.Activity#onDestroy() onDestroy} call.
     */
    DESTROYED,
    INITIALIZED,
    CREATED,
    STARTED,
    RESUMED;
}

可以看到Event枚举类里除了ON_ANY事件,其他事件几乎是跟Activity的生命周期对应,下图是事件与状态的对应关系:

生命周期状态示意图

之前提到Lifecycle的默认实现类是LifecycleRegistry,我们先去构造方法看一下:

public LifecycleRegistry(@NonNull LifecycleOwner provider) {
    mLifecycleOwner = new WeakReference<>(provider);
    mState = INITIALIZED;
}

可以看到构造方法内传入了一个LifecycleOwner对象,之前在Activity调用了getLifecycle方法,我们点进去看一下,其实是返回了一个LifecycleRegistry对象,而这个对象传入了当前Activity到构造函数:

public class ComponentActivity extends androidx.core.app.ComponentActivity{
    public Lifecycle getLifecycle() {
    	return mLifecycleRegistry;
	}
    private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
}

到这里我们整理一下:

1.Lifecycle的默认实现是LifecycleRegistry,构造函数需要传入LifecycleOwner对象。

2.getLifecycle返回了LifecycleRegistry对象,LifecycleRegistry对象是将调用了getLifecycle的Activity当作参数传入构造函数。

3.因此在Activity中调用addObserver方法实际上是调用的以当前的Activity为参数构造的LifecycleRegistry的addObserver方法。

Lifecycle的分析先停一停,我们来看LifecycleOwner。

2.LifecycleOwner

之前明明提到LifecycleRegistry的构造函数需要传入LifecycleOwner对象,但是通过getLifecycle我们可以看到,实际上传入的是当前Activity,到这里应该都猜到了Activity是实现了LifecycleOwner接口的。事实上也是如此,在库 26.1.0 及更高版本中的Fragment和Activity已实现LifecycleOwner接口,因此我们直接传入了Activity本身。

LifecycleOwner接口里面也只有一个getLifecycle方法,返回了具体的Lifecycle对象,也就是LifecycleRegistry:

public interface LifecycleOwner {
    Lifecycle getLifecycle();
}

到这里可以明白,每个Activity存在了一个以自身为构造参数的LifecycleRegistry私有成员对象,通过getLifecycle可以拿到这个私有的LifecycleRegistry对象,并且对它进行addObserver,removeObserver等方法。

3.LifecycleRegistry

既然Activity拿到的是一个具体的LifecycleRegistry对象,我们回到LifecycleRegistry去看它的具体实现:

public class LifecycleRegistry extends Lifecycle {
    //省略
    ...
    @Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        Lifecycle.State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        //将observer对象和状态一起封装到ObserverWithState类中
        LifecycleRegistry.ObserverWithState statefulObserver = new LifecycleRegistry.ObserverWithState(observer, initialState);
        LifecycleRegistry.ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

        if (previous != null) {
            return;
        }
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            // it is null we should be destroyed. Fallback quickly
            return;
        }

        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
        Lifecycle.State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            //分发事件
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            // mState / subling may have been changed recalculate
            targetState = calculateTargetState(observer);
        }

        if (!isReentrance) {
            // we do sync only on the top level.
            sync();
        }
        mAddingObserverCounter--;
    }
    ...
    //省略
}

LifecycleRegistry对象的addObserver方法我们可以分两步来看,第一步将observer(观察者)以及initialState封装到ObserverWithState类:

static class ObserverWithState {
    State mState;
    LifecycleEventObserver mLifecycleObserver;

    ObserverWithState(LifecycleObserver observer, State initialState) {
        mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
        mState = initialState;
    }
    void dispatchEvent(LifecycleOwner owner, Event event) {
        State newState = getStateAfter(event);
        mState = min(mState, newState);
        mLifecycleObserver.onStateChanged(owner, event);
        mState = newState;
    }
}

其实是为了将observer统一封装成LifecycleEventObserver对象,方便事件的分发。

第二步通过while循环比较状态将事件分发出去,也就是调用了ObserverWithState的dispatchEvent方法,实际上也就是LifecycleEventObserver对象的onStateChanged方法。

因此可以看到LifecycleRegistry的addObserver方法做的事是将observer也就是观察者封装成ObserverWithState对象,当然最终目的是封装成LifecycleEventObserver,方便事件的统一分开,最后去调用对应observer的onStateChanged方法完成观察者通知。

4.LifecycleObserver

上面可以看到LifecycleRegistry保证了切换状态时会将事件分发到观察者,因此我们只需要在观察者类中实现自己的逻辑。

LifecycleObserver是一个空接口:

public interface LifecycleObserver {

}

其中LifecycleEventObserver,FullLifecycleObserver 都是继承LifecycleObserver的接口,算是两种不同的默认实现:

public interface LifecycleEventObserver extends LifecycleObserver {
    void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}
interface FullLifecycleObserver extends LifecycleObserver {

    void onCreate(LifecycleOwner owner);

    void onStart(LifecycleOwner owner);

    void onResume(LifecycleOwner owner);

    void onPause(LifecycleOwner owner);

    void onStop(LifecycleOwner owner);

    void onDestroy(LifecycleOwner owner);
}

这就涉及到我的知识盲区了,为什么接口用的是extends,这就是官方接口的好处吗。

我们可以实现LifecycleEventObserver接口,根据不同的Event写逻辑,也可以实现FullLifecycleObserver接口,在对应的方法中写需要的逻辑,而细心的小伙伴应该会发现最最最上面的例子用的注解的形式,需要通过反射进行回调,已经不推荐使用了,最好是使用接口的形式去实现观察者类。

5.LifecycleOwner分发细节

综上可知,LifecycleOwner(暂时考虑实现LifecycleOwner接口的Activity)内部是有一个以自身为构造参数的LifecycleRegistry私有成员对象,完成绑定后,Activity控制LifecycleRegistry对象负责在不同的生命周期分发事件给具体的观察者,也就是LifecycleEventObserver,于是我们只需要自定义实现对应方法就可以让组件能够感知生命周期。

那么Activity控制LifecycleRegistry对象负责在不同的生命周期分发事件是怎么实现的呢?

我们定位到Activity的onCreate方法,这里有个ReportFragment.injectIfNeededIn(this),将自身为参数调用了injectIfNeededIn静态方法,其实我也不知道是怎么追踪到这里去的:

public class ComponentActivity implements LifecycleOwner {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //分发的入口
        ReportFragment.injectIfNeededIn(this);
        ...
    }
}

由于写在onCreate方法里面,Activity创建时就会调用该方法,点进去看一下:

public static void injectIfNeededIn(Activity activity) {
    // ProcessLifecycleOwner should always correctly work and some activities may not extend
    // FragmentActivity from support lib, so we use framework fragments for activities
    android.app.FragmentManager manager = activity.getFragmentManager();
    if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
        //创建一个空的ReportFragment
        manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
        // Hopefully, we are the first to make a transaction.
        manager.executePendingTransactions();
    }
}

这里创建了一个空的Fragment依附在Activity上面,这样的话它们的生命周期是一致的,因此我们只要在ReportFragment对应的生命周期去分发事件即可:

public class ReportFragment {
    //只保留部分代码
    @Override
    public void onStart() {
        super.onStart();
        dispatch(Lifecycle.Event.ON_START);
    }

    @Override
    public void onResume() {
        super.onResume();
        dispatch(Lifecycle.Event.ON_RESUME);
    }
    ...
}

可以看到生命周期里果然分发了Lifecycle.Event事件,最后点进去dispatch函数看一下细节:

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所属的Activity的成员变量LifecycleRegistry,然后进行事件的分发,于是那些绑定的观察者在正确的生命周期里获得了回调。

到此,这篇Lifecycle实现浅析已经到了尾声,关于生命周期状态的同步,Activity的生命周期为什么会和ReportFragment一致的问题就不一一道来了。简单地总结一下就是:

1.LifecycleOwner(Activity)内部有一个LifecycleRegistry对象,绑定了对应的LifecycleObserver对象。

2.LifecycleRegistry在对应的生命周期分发了事件,被LifecycleObserver观察到。

3.正是考虑了生命周期的观察者模式,Lifecycle组件让自定义类获得了生命周期感知能力。

奇思妙用:监听应用前后台切换

前面我们对Lifecycle的组件的分析基本上基于Activity,其实对Server,Application的支持也都大同小异,这里就不一一去看源码了。

如果我们要监听应用前后台切换,我们可以使用ProcessLifecycleOwner,看名字也猜得出来这是基于整个进程的被观察者接口,只要创建对应的观察者,绑定即可:

public class MusicService implements DefaultLifecycleObserver {
    private final String activityTag = getClass().getName();

    @Override
    public void onStart(@NonNull LifecycleOwner owner) {
        Log.e(activityTag, "前台:start");
    }

    @Override
    public void onResume(@NonNull LifecycleOwner owner) {
        Log.e(activityTag, "前台:resume");
    }
    @Override
    public void onPause(@NonNull LifecycleOwner owner) {
        Log.e(activityTag, "后台:pause");
    }
    @Override
    public void onStop(@NonNull LifecycleOwner owner) {
        Log.e(activityTag, "后台:stop");
    }

}
public class MainActivity extends AppCompatActivity {

    private MusicService musicService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    private void init() {
        musicService = new MusicService();
        ProcessLifecycleOwner.get().getLifecycle().addObserver(musicService);
    }
}

实现方式很简单,这样我们就可以监听进程的前后台切换了,不过这个功能实际用处暂时没想到?如果想知道ProcessLifecycleOwner的具体实现细节,可以参考mp.weixin.qq.com/s/ZXqrrX2Hd…