小松的技术博客

六和敬

若今生迷局深陷,射影含沙。便许你来世袖手天下,一幕繁华。 你可愿转身落座,掌间朱砂,共我温酒煮茶。

Android架构之美-Lifecycle

自 2017 年, Google推出了很多架构组件,使得开发一个新的 app 变得更加容易。在使用这些组件后,你会有一种身心愉悦的感受:这些组件设计得太流弊了。 当然,不能只是停留在使用的层面,去源码中看看这些组件开发者是如何设计的,更有益于我们的成长。

首先来感受下,官方 Lifecycle 组件的设计。 Android 的生命周期管理一直是个老生常谈的问题,很多功能都需要考虑生命周期的问题。例如,onStop 后不要去做发送网络请求、更新UI、请求地理位置等工作。 在没有 Lifecycle 组件之前,我们往往会在 Activity 或者 Fragment 里面的生命钩子函数里做很多事情,如果使用 MVP 模式,则需要在 Presenter 里面提供一系列生命钩子。

如 Google 提供的示例:

class LocationListener(context: Context, cb: Callback) {

    fun start() {
        // connect to system location service
    }

    fun stop() {
        // disconnect from system location service
    }
}

class MyActivity: AppCompatActivity() {  
    private var locationListener: LocationListener? = null

    override fun onCreate(...) {
        //...
        locationListener = LocationListener(this) {
            // update UI
        }
    }

    override fun onStart() {
        super.onStart();
        locationListener?.start();
        // manage other components that need to respond
        // to the activity lifecycle
    }

    override fun onStop() {
        super.onStop();
        locationListener?.stop();
        // manage other components that need to respond
        // to the activity lifecycle
    }
}

而在使用 lifecycle 以后,代码可以变为:

class LocationListener(context: Context, cb: Callback): LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun start() {
        // connect to system location service
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun stop() {
        // disconnect from system location service
    }
}

class MyActivity: AppCompatActivity() {  
    override fun onCreate(...) {
        //...
        lifecycle.addObserver(LocationListener(this){
            // update UI
        })
    }
}

代码一对比, 功能代码基本上去都抽取出去了,这个 Activity/Fragment 代码就清爽多了。

Lifecycle 的状态与事件变化

Lifecycle 与 LifecycleOwner

Lifecycle 接口只提供了 addObserverremoveObserver 两个方法,内部给出了唯一实现 LifecycleRegistry。 简单来说,这是个观察者模式,但里面有一些关于注解的玩法,使得使用更灵活。

LifecycleOwner 接口只有一个方法: getLifecycle()。在高版本和 androidX 里的 Activity、Fragment 基本上都实现了 LifecycleOwner 接口,因此我们可以直接在 Activity/Fragment 里通过getLifecycle()拿到 Lifecycle

LifecycleObserver

public interface LifecycleObserver {

}

当我们看到LifecycleObserver这个接口时,第一感觉是比较奇怪:这个接口竟然是空的。这或许这是因为生命周期钩子比较多,如果全都放在接口里,那么实现者需要添加很多空实现方法,可阅读性降低。因此,LifecycleObserver 需要配合注解 OnLifecycleEvent 使用,LifecycleObserver 只是起一个声明和约束作用。其内部继承数如下图:

使用者可以视情况选择 LifecycleObserverFullLifecycleObserverGenericLifecycleObserver, 但框架内部都会将其转换为GenericLifecycleObserver 或其子类。 其转换行为在类 Lifecycling 中。

static GenericLifecycleObserver getCallback(Object object) {  
    // 如果是 FullLifecycleObserver, 转换为 FullLifecycleObserverAdapter
    if (object instanceof FullLifecycleObserver) {
        return new FullLifecycleObserverAdapter((FullLifecycleObserver) object);
    }
    // 如果是 GenericLifecycleObserver, 不转换
    if (object instanceof GenericLifecycleObserver) {
        return (GenericLifecycleObserver) object;
    }

    final Class<?> klass = object.getClass();
    // 获取转换type, GENERATED_CALLBACK 为使用代码生成,REFLECTIVE_CALLBACK 为使用反射调用
    int type = getObserverConstructorType(klass);
    if (type == GENERATED_CALLBACK) {
        // 采用代码生成
        List<Constructor<? extends GeneratedAdapter>> constructors =
        sClassToAdapters.get(klass);
        if (constructors.size() == 1) {
            GeneratedAdapter generatedAdapter = createGeneratedAdapter(
                    constructors.get(0), object);
            return new SingleGeneratedAdapterObserver(generatedAdapter);
        }
        GeneratedAdapter[] adapters = new GeneratedAdapter[constructors.size()];
        for (int i = 0; i < constructors.size(); i++) {
            adapters[i] = createGeneratedAdapter(constructors.get(i), object);
        }
        return new CompositeGeneratedAdaptersObserver(adapters);
    }
    // 默认采用反射调用
    return new ReflectiveGenericLifecycleObserver(object);
}

如何决定是采用代码生成还是反射调用呢?如果引用了注解生成器kapt "android.arch.lifecycle:compiler:1.1.1", 则会生成相应的 GeneratedAdapter子类。反之就不会有相应的生成类。因此,如果有找到生成类,则采用代码生成方式,否则采取反射调用。

private static int resolveObserverCallbackType(Class<?> klass) {  
    // 匿名内部类采用反射
    if (klass.getCanonicalName() == null) {
        return REFLECTIVE_CALLBACK;
    }
    // 寻找生成类
    Constructor<? extends GeneratedAdapter> constructor = generatedConstructor(klass);
    if (constructor != null) {
        // 找到生成类,则采用 GENERATED_CALLBACK
        sClassToAdapters.put(klass, Collections
                .<Constructor<? extends GeneratedAdapter>>singletonList(constructor));
        return GENERATED_CALLBACK;
    }

    // 是否有方法被 OnLifecycleEvent 注解
    boolean hasLifecycleMethods = ClassesInfoCache.sInstance.hasLifecycleMethods(klass);
    if (hasLifecycleMethods) {
        // 如果有方法被 OnLifecycleEvent 注解, 则采用反射
        return REFLECTIVE_CALLBACK;
    }

    // 如果没有找到生成类,也没有方法被 OnLifecycleEvent 注解。 我们需要去看其父类和接口,或许它们被注解,因此这里又递归调用
    Class<?> superclass = klass.getSuperclass();
    List<Constructor<? extends GeneratedAdapter>> adapterConstructors = null;
    // 如果父类实现了 LifecycleObserver
    if (isLifecycleParent(superclass)) {
        if (getObserverConstructorType(superclass) == REFLECTIVE_CALLBACK) {
            return REFLECTIVE_CALLBACK;
        }
        adapterConstructors = new ArrayList<>(sClassToAdapters.get(superclass));
    }

    // 如果有接口继承了 LifecycleObserver
    for (Class<?> intrface : klass.getInterfaces()) {
        if (!isLifecycleParent(intrface)) {
            continue;
        }
        if (getObserverConstructorType(intrface) == REFLECTIVE_CALLBACK) {
            return REFLECTIVE_CALLBACK;
        }
        if (adapterConstructors == null) {
            adapterConstructors = new ArrayList<>();
        }
        adapterConstructors.addAll(sClassToAdapters.get(intrface));
    }
    if (adapterConstructors != null) {
        sClassToAdapters.put(klass, adapterConstructors);
        return GENERATED_CALLBACK;
    }

    return REFLECTIVE_CALLBACK;
}

addObserver 实现

addObserver 并不是简单的将 Observer 加入 map 中, 首先它会做上文提到的 Observer 转换。 其次需要考虑“重入问题”。 所谓的“重入问题”,就是 addObserver 会触发 Observer 生命周期函数的调用,而 Observer 在生命周期函数中又调用了 addObserver 等方法。 因此, LifecycleRegistry 用变量 mAddingObserverCountermHandlingEvent 来判断是否处于重入状态。

public void addObserver(@NonNull LifecycleObserver observer) {  
    State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
    // ObserverWithState里会做 Observer 的转换
    ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
    // 放入 map 中
    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;
    // 引入 parentState, targetState 等都是为了保证列表中后加的 Observer 的状态不能大于前面的, 这样做之后,如果列表第一个和最后一个的状态和 LifecycleRegistry.mState 相等时,就说明状态同步完成了。
    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--;
}

如果是我实现观察者模式,如果没有遇到bug, 基本上不会考虑重入问题,读源码后,瞬间涨见识了。

状态更改分发

每个 Observer 都有自己的当前状态,然后需要在 lifecycle 状态改变时通知 Observer 移动状态到确定的位置。那么问题来了,如何所有 Observer 的状态都完成同步?LifecycleRegistry 给出的思路是:程序保证后加入 map 的 Observer 状态不能大于 map 前面的状态,在这个前提下,如果 map 中第一个 Observer 和最后一个 Observer 的状态相等,并且等于 lifecycle 的状态时,就说明完成同步。

如何保证后加入 map 的 Observer 不能大于 map 前面的状态呢?

  1. addObserver 时调用 calculateTargetState(observer)。 取 map 中前一个的状态、parentState、自身 state 的前者。
  2. parentState 是为了应对重入问题, 重入的 addObserver 状态不能走到外层 addObserver 前面去。
  3. 状态更改分发时,如果状态减小,则 map 从后往前遍历执行分发;如果状态增加,则 map 从前往后遍历执行分发。
// move 到指定状态
public void markState(@NonNull State state) {  
    moveToState(state);
}
// 根据 event 去觉得状态
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 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;
}

ReflectiveGenericLifecycleObserver 反射实现

前面说过,使用者使用注解后,可以选择代码生成方式或者反射调用方式,代码生成方式有兴趣的可以去看看生成后的 Adapter 代码,这里来看看 ReflectiveGenericLifecycleObserver 的实现,巩固巩固反射知识。

class ReflectiveGenericLifecycleObserver implements GenericLifecycleObserver {  
    private final Object mWrapped;
    private final CallbackInfo mInfo;

    ReflectiveGenericLifecycleObserver(Object wrapped) {
        mWrapped = wrapped;
        mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass());
    }

    @Override
    public void onStateChanged(LifecycleOwner source, Event event) {
        mInfo.invokeCallbacks(source, event, mWrapped);
    }
}

其关键部分为 CallbackInfo 的构造:ClassesInfoCache.sInstance.getInfo(mWrapped.getClass())

首先看下 CallbackInfo 的结构:

static class CallbackInfo {  
    // 事件 -> 方法列表
    final Map<Lifecycle.Event, List<MethodReference>> mEventToHandlers;
    // 方法 -> 事件
    final Map<MethodReference, Lifecycle.Event> mHandlerToEvent;

    CallbackInfo(Map<MethodReference, Lifecycle.Event> handlerToEvent) {
        mHandlerToEvent = handlerToEvent;
        mEventToHandlers = new HashMap<>();
        for (Map.Entry<MethodReference, Lifecycle.Event> entry : handlerToEvent.entrySet()) {
            Lifecycle.Event event = entry.getValue();
            List<MethodReference> methodReferences = mEventToHandlers.get(event);
            if (methodReferences == null) {
                methodReferences = new ArrayList<>();
                mEventToHandlers.put(event, methodReferences);
            }
            methodReferences.add(entry.getKey());
        }
    }

    @SuppressWarnings("ConstantConditions")
    void invokeCallbacks(LifecycleOwner source, Lifecycle.Event event, Object target) {
        // 事件分发与处理
        invokeMethodsForEvent(mEventToHandlers.get(event), source, event, target);
        invokeMethodsForEvent(mEventToHandlers.get(Lifecycle.Event.ON_ANY), source, event,
                target);
    }

    private static void invokeMethodsForEvent(List<MethodReference> handlers,
    LifecycleOwner source, Lifecycle.Event event, Object mWrapped) {
        if (handlers != null) {
            for (int i = handlers.size() - 1; i >= 0; i--) {
                // 遍历,调用 MethodReference.invokeCallback
                handlers.get(i).invokeCallback(source, event, mWrapped);
            }
        }
    }
}

因此 CallbackInfo 实质是将这个类的注解事件与方法提取出来,做了一个双向 map。

CallbackInfo getInfo(Class klass) {  
    // 先读取缓存
    CallbackInfo existing = mCallbackMap.get(klass);
    if (existing != null) {
        return existing;
    }
    // create
    existing = createInfo(klass, null);
    return existing;
}

private CallbackInfo createInfo(Class klass, @Nullable Method[] declaredMethods) {  
    // 先提取父类的 CallbackInfo
    Class superclass = klass.getSuperclass();
    Map<MethodReference, Lifecycle.Event> handlerToEvent = new HashMap<>();
    if (superclass != null) {
        CallbackInfo superInfo = getInfo(superclass);
        if (superInfo != null) {
            handlerToEvent.putAll(superInfo.mHandlerToEvent);
        }
    }

    // 再提取接口的 CallbackInfo
    Class[] interfaces = klass.getInterfaces();
    for (Class intrfc : interfaces) {
        for (Map.Entry<MethodReference, Lifecycle.Event> entry : getInfo(
                intrfc).mHandlerToEvent.entrySet()) {
        // verifyAndPutHandler 的作用是实现了接口或者覆写了父类的方法,但是添加了不同的注解事件。
        verifyAndPutHandler(handlerToEvent, entry.getKey(), entry.getValue(), klass);
    }

    // 最后处理类自身的注解
    Method[] methods = declaredMethods != null ? declaredMethods : getDeclaredMethods(klass);
    boolean hasLifecycleMethods = false;
    // 遍历方法,寻找被 OnLifecycleEvent 注解的方法
    for (Method method : methods) {
        OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);
        if (annotation == null) {
            continue;
        }
        hasLifecycleMethods = true;
        // 处理参数个数,最多两个参数
        Class<?>[] params = method.getParameterTypes();
        int callType = CALL_TYPE_NO_ARG;
        if (params.length > 0) {
            callType = CALL_TYPE_PROVIDER;
            if (!params[0].isAssignableFrom(LifecycleOwner.class)) {
                        throw new IllegalArgumentException(
                                "invalid parameter type. Must be one and instanceof LifecycleOwner");
                    }
        }
        Lifecycle.Event event = annotation.value();

        if (params.length > 1) {
            callType = CALL_TYPE_PROVIDER_WITH_EVENT;
            if (!params[1].isAssignableFrom(Lifecycle.Event.class)) {
                        throw new IllegalArgumentException(
                                "invalid parameter type. second arg must be an event");
                    }
                if (event != Lifecycle.Event.ON_ANY) {
                    throw new IllegalArgumentException(
                            "Second arg is supported only for ON_ANY value");
                }
        }
        if (params.length > 2) {
            throw new IllegalArgumentException("cannot have more than 2 params");
        }
        MethodReference methodReference = new MethodReference(callType, method);
        verifyAndPutHandler(handlerToEvent, methodReference, event, klass);
    }
    // new CallbackInfo
    CallbackInfo info = new CallbackInfo(handlerToEvent);
    // 放入缓存中
    mCallbackMap.put(klass, info);
    mHasLifecycleMethods.put(klass, hasLifecycleMethods);
    return info;
}

好了,Lifecycle 的核心内容差不多就这些了,希望对大家有用。

←微信← →支付宝 →