@OnLifecycleEnvent 被廢棄,替代方案更簡單

語言: CN / TW / HK

highlight: androidstudio theme: smartblue


近期 androidx.lifecycle 釋出了 2.4.0 版本,此次更新中 @OnLifecycleEvent 註解被廢棄,官方建議使用 LifecycleEventObserver 或者 DefaultLifecycleObserver 替代

現代的 Android 應用中都少不了 Lifecycle 的身影,正是各種 lifecycle-aware 元件的存在保證了程式的健壯性。

Lifecycle 本質是一個觀察者模式的最佳實踐,通過實現 LifecycleObserver 介面,開發者可以自自定 lifecycle-aware 元件,感知 Activity 或 Fragment 等 LifecycleOwner 的生命週期回撥。

趁新版本釋出之際,我們再回顧一下 Lifecycle 註解的使用以及廢棄後的替代方案

Lifecycle Events & States

Lifecyce 使用兩組列舉分別定義了 EventState

  • Events
  • ON_CREATE
  • ON_START
  • ON_RESUME
  • ON_PAUSE
  • ON_STOP
  • ON_DESTROY
  • ON_ANY

  • States

  • INITIALIZED
  • CREATED
  • STARTED
  • RESUMED
  • DESTROYED

Events 對應了 Activity 等原生系統元件的生命後期回撥, 每當 Event 發生時意味著這些 LifecycleOwner 進入到一個新的 State

作為 觀察者的 LifecycleObserver 可以感知到 被觀察者的 LifecycleOwner 其生命週期 State 變化時的 Event。定義 LifecycleObserver 有三種方式: 1. 實現 LifecycleEventObserver 介面 2. 使用 @OnLifecycleEvent 註解

實現 LifecycleEventObserver

java public interface LifecycleEventObserver extends LifecycleObserver { void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event); } LifecycleEventObserver 是一個單方法介面,在 Kotlin 中可轉為寫法更簡潔的 Lambda 進行宣告 kotlin val myEventObserver = LifecycleEventObserver { source, event -> when(event) { Lifecycle.Event.ON_CREATE -> TODO() Lifecycle.Event.ON_START -> TODO() else -> TODO() } } LifecycleEventObserver 本身就是 LifecycleObserver 的派生,使用時直接 addObserver 到 LivecycleOwner 的 Lifecycle 即可。

需要在 onStateChanged 中寫 swich / case 自己分發事件。相對於習慣重寫 Activity 或者 Fragment 的 onCreateonResume 等方法,稍顯囉嗦。

因此 Lifecycle 給我們準備了 @OnLifecycleEvent 註解

使用 @OnLifecycleEvent 註解

使用方法很簡單,繼承 LifecycleObserver 介面,然後在成員方法上添加註解即可

```kotlin val myEventObserver = object : LifecycleObserver {

@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onStart() {
    TODO()
}

@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreat() {
    TODO()
}

} ```

添加註冊後,到 LifecycleOwner 的 Event 分發時,會自動回撥註解匹配的成員方法,由於省去了手動 switch/case 的過程,深受開發者喜歡

註解解析過程

Event 分發時,怎麼就會回到到註解對應的方法的?

通過 addObserver 新增的 LifecycleObserver ,都會轉為一個 LifecycleEventObserver ,LifecycleOwner 通過呼叫其 onStateChanged 分發 Event

Lifecycling#lifecycleEventObserver 中處理轉換

```java public class Lifecycling {

@NonNull
static LifecycleEventObserver lifecycleEventObserver(Object object) {
    boolean isLifecycleEventObserver = object instanceof LifecycleEventObserver;
    boolean isFullLifecycleObserver = object instanceof FullLifecycleObserver;
    // 觀察者是 FullLifecycleObserver
    if (isLifecycleEventObserver && isFullLifecycleObserver) {
        return new FullLifecycleObserverAdapter((FullLifecycleObserver) object,
                (LifecycleEventObserver) object);
    }

    // 觀察者是 LifecycleEventObserver
    if (isFullLifecycleObserver) {
        return new FullLifecycleObserverAdapter((FullLifecycleObserver) object, null);
    }

    if (isLifecycleEventObserver) {
        return (LifecycleEventObserver) object;
    }

    final Class<?> klass = object.getClass();
    int type = getObserverConstructorType(klass);

    // 觀察者是通過 apt 產生的類
    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);
    }

    // 觀察者需要通過反射生成一個 wrapper
    return new ReflectiveGenericLifecycleObserver(object);
}

...

public static String getAdapterName(String className) {
    return className.replace(".", "_") + "_LifecycleAdapter";
}

} ```

邏輯很清晰,根據 LifecycleObserver 型別不用轉成不同的 LifecycleEventObserver,

用一段虛擬碼梳理如下:

kotlin if (lifecycleObserver is FullLifecycleObserver) { return FullLifecycleObserverAdapter // 後文介紹 } else if (lifecycleObserver is LifecycleEventObserver) { return this } else if (type == GENERATED_CALLBACK) { return GeneratedAdaptersObserver } else {// type == REFLECTIVE_CALLBACK return ReflectiveGenericLifecycleObserver }

註解有兩種使用用途。

場景一:runtime 時期使用反射生成 wrapper

```java class ReflectiveGenericLifecycleObserver implements LifecycleEventObserver { 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 是關鍵,通過反射收集當前 LifecycleObserver 的回撥資訊。onStateChanged 中通過反射呼叫時,不會因為因為缺少 method 報錯。

場景二:編譯時使用 apt 生成 className + _LifecycleAdapter

除了利用反射, Lifecycle 還提供了 apt 方式處理註解。

新增 gradle 依賴: groovy dependencies { // java 寫法 annotationProcessor "androidx.lifecycle:lifecycle-compiler:2.3.1" // kotlin 寫法 kapt "androidx.lifecycle:lifecycle-compiler:2.3.1" } 這樣在編譯器就會根據 LifecyceObserver 類名生成一個新增 _LifecycleAdapter 字尾的類。 比如我們加了 onCreatonStart 的註解,生成的程式碼如下: ```java public class MyEventObserver_LifecycleAdapter implements GeneratedAdapter { final MyEventObserver mReceiver;

MyEventObserver_LifecycleAdapter(MyEventObserver receiver) { this.mReceiver = receiver; }

@Override public void callMethods(LifecycleOwner owner, Lifecycle.Event event, boolean onAny, MethodCallsLogger logger) { boolean hasLogger = logger != null; if (onAny) { return; } if (event == Lifecycle.Event.ON_CREATE) { if (!hasLogger || logger.approveCall("onCreate", 1)) { mReceiver.onCreate(); } return; } if (event == Lifecycle.Event.ON_START) { if (!hasLogger || logger.approveCall("onStart", 1)) { mReceiver.onStart(); } return; } } } ```

apt 減少了反射的呼叫,效能更好,當然會犧牲一些編譯速度。

為什麼要使用註解

生命週期的 Event 種類很多,我們往往不需要全部實現,如過不使用註解,可能需要實現所有方法,產生額外的無用程式碼

上面程式碼中的 FullLifecycleObserver 就是一個全部方法的介面

```java 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);

} ```

從介面不是 public 的( java 程式碼 ) 可以看出,官方也無意讓我們使用這樣的介面,增加開發者負擔。

遭廢棄的原因

既然註解這麼好,為什麼又要廢棄呢?

This annotation required the usage of code generation or reflection, which should be avoided.

從官方文件的註釋可以看到,註解要麼依賴反射降低執行時效能,要麼依靠 APT 降低編譯速度,不是完美的方案。

我們之所引入註解,無非是不想多實現幾個空方法。早期 Android 工程不支援 Java8 編譯,介面沒有 default 方法, 現如今 Java8 已經是預設配置,可以為介面新增 default 方法,此時註解已經失去了存在的意義。

如今官方推薦使用 DefaultLifecycleObserver 介面來定義你的 LifecycleObserver

``` java 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) {
}

} ```

FullLifecycleObserverAdapter, 無腦回調 FullLifecycleObserver 即可 ```java class FullLifecycleObserverAdapter implements GenericLifecycleObserver {

private final FullLifecycleObserver mObserver;

FullLifecycleObserverAdapter(FullLifecycleObserver observer) {
    mObserver = observer;
}

@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
    switch (event) {
        case ON_CREATE:
            mObserver.onCreate(source);
            break;
        case ON_START:
            mObserver.onStart(source);
            break;
        case ON_RESUME:
            mObserver.onResume(source);
            break;
        case ON_PAUSE:
            mObserver.onPause(source);
            break;
        case ON_STOP:
            mObserver.onStop(source);
            break;
        case ON_DESTROY:
            mObserver.onDestroy(source);
            break;
        case ON_ANY:
            throw new IllegalArgumentException("ON_ANY must not been send by anybody");
    }
}

} `` 需要注意DefaultLifecycleObserver在 2.4.0 之前也是可以使用的, 存在於androidx.lifecycle.lifecycle-common-java8這個庫中, 2.4.0 開始 統一移動到androidx.lifecycle.lifecycle-common` 了 ,已經沒有 java8 單獨的擴充套件庫了。