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

現代的 Android 應用中都少不了 Lifecycle 的身影,正是各種 lifecycle-aware 組件的存在保證了程序的健壯性。
Lifecycle 本質是一個觀察者模式的最佳實踐,通過實現 LifecycleObserver 接口,開發者可以自自定 lifecycle-aware 組件,感知 Activity 或 Fragment 等 LifecycleOwner 的生命周期回調。
趁新版本發布之際,我們再回顧一下 Lifecycle 註解的使用以及廢棄後的替代方案
Lifecycle Events & StatesLifecyce 使用兩組枚舉分別定義了 Event 和 State。
Events
States
Events 對應了 Activity 等原生系統組件的生命後期回調, 每當 Event 發生時意味着這些 LifecycleOwner 進入到一個新的 State。

作為 觀察者的 LifecycleObserver 可以感知到 被觀察者的 LifecycleOwner 其生命周期 State 變化時的 Event。定義 LifecycleObserver 有三種方式:
LifecycleEventObserver 是一個單方法接口,在 Kotlin 中可轉為寫法更簡潔的 Lambda 進行聲明
valmyEventObserver=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 的 onCreate, onResume 等方法,稍顯囉嗦。
因此 Lifecycle 給我們準備了 @OnLifecycleEvent 註解
使用 @OnLifecycleEvent 註解使用方法很簡單,繼承 LifecycleObserver 接口,然後在成員方法上添加註解即可
valmyEventObserver=object:LifecycleObserver{@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)funonStart(){TODO()}@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)funonCreat(){TODO()}}添加註冊後,到 LifecycleOwner 的 Event 分發時,會自動回調註解匹配的成員方法,由於省去了手動 switch/case 的過程,深受開發者喜歡
註解解析過程Event 分發時,怎麼就會回到到註解對應的方法的?
通過 addObserver 添加的 LifecycleObserver ,都會轉為一個 LifecycleEventObserver ,LifecycleOwner 通過調用其 onStateChanged 分發 Event
在 Lifecycling#lifecycleEventObserver 中處理轉換
publicclassLifecycling{@NonNullstaticLifecycleEventObserverlifecycleEventObserver(Objectobject){booleanisLifecycleEventObserver=objectinstanceofLifecycleEventObserver;booleanisFullLifecycleObserver=objectinstanceofFullLifecycleObserver;//觀察者是FullLifecycleObserverif(isLifecycleEventObserver&&isFullLifecycleObserver){returnnewFullLifecycleObserverAdapter((FullLifecycleObserver)object,(LifecycleEventObserver)object);}//觀察者是LifecycleEventObserverif(isFullLifecycleObserver){returnnewFullLifecycleObserverAdapter((FullLifecycleObserver)object,null);}if(isLifecycleEventObserver){return(LifecycleEventObserver)object;}finalClass<?>klass=object.getClass();inttype=getObserverConstructorType(klass);//觀察者是通過apt產生的類if(type==GENERATED_CALLBACK){List<Constructor<?extendsGeneratedAdapter>>constructors=sClassToAdapters.get(klass);if(constructors.size()==1){GeneratedAdaptergeneratedAdapter=createGeneratedAdapter(constructors.get(0),object);returnnewSingleGeneratedAdapterObserver(generatedAdapter);}GeneratedAdapter[]adapters=newGeneratedAdapter[constructors.size()];for(inti=0;i<constructors.size();i++){adapters[i]=createGeneratedAdapter(constructors.get(i),object);}returnnewCompositeGeneratedAdaptersObserver(adapters);}//觀察者需要通過反射生成一個wrapperreturnnewReflectiveGenericLifecycleObserver(object);}...publicstaticStringgetAdapterName(StringclassName){returnclassName.replace(".","_")+"_LifecycleAdapter";}}邏輯很清晰,根據 LifecycleObserver 類型不用轉成不同的 LifecycleEventObserver,
用一段偽代碼梳理如下:
if(lifecycleObserverisFullLifecycleObserver){returnFullLifecycleObserverAdapter//後文介紹}elseif(lifecycleObserverisLifecycleEventObserver){returnthis}elseif(type==GENERATED_CALLBACK){returnGeneratedAdaptersObserver}else{//type==REFLECTIVE_CALLBACKreturnReflectiveGenericLifecycleObserver}註解有兩種使用用途。
場景一:runtime 時期使用反射生成 wrapperclassReflectiveGenericLifecycleObserverimplementsLifecycleEventObserver{privatefinalObjectmWrapped;privatefinalCallbackInfomInfo;ReflectiveGenericLifecycleObserver(Objectwrapped){mWrapped=wrapped;mInfo=ClassesInfoCache.sInstance.getInfo(mWrapped.getClass());}@OverridepublicvoidonStateChanged(LifecycleOwnersource,Eventevent){mInfo.invokeCallbacks(source,event,mWrapped);}}CallbackInfo 是關鍵,通過反射收集當前 LifecycleObserver 的回調信息。onStateChanged 中通過反射調用時,不會因為因為缺少 method 報錯。
場景二:編譯時使用 apt 生成 className + _LifecycleAdapter除了利用反射, Lifecycle 還提供了 apt 方式處理註解。
添加 gradle 依賴:
dependencies{//java寫法annotationProcessor"androidx.lifecycle:lifecycle-compiler:2.3.1"//kotlin寫法kapt"androidx.lifecycle:lifecycle-compiler:2.3.1"}這樣在編譯器就會根據 LifecyceObserver 類名生成一個添加 _LifecycleAdapter 後綴的類。比如我們加了 onCreat 和 onStart 的註解,生成的代碼如下:
publicclassMyEventObserver_LifecycleAdapterimplementsGeneratedAdapter{finalMyEventObservermReceiver;MyEventObserver_LifecycleAdapter(MyEventObserverreceiver){this.mReceiver=receiver;}@OverridepublicvoidcallMethods(LifecycleOwnerowner,Lifecycle.Eventevent,booleanonAny,MethodCallsLoggerlogger){booleanhasLogger=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 就是一個全部方法的接口
interfaceFullLifecycleObserverextendsLifecycleObserver{voidonCreate(LifecycleOwnerowner);voidonStart(LifecycleOwnerowner);voidonResume(LifecycleOwnerowner);voidonPause(LifecycleOwnerowner);voidonStop(LifecycleOwnerowner);voidonDestroy(LifecycleOwnerowner);}從接口不是 public 的( java 代碼 ) 可以看出,官方也無意讓我們使用這樣的接口,增加開發者負擔。
遭廢棄的原因既然註解這麼好,為什麼又要廢棄呢?
This annotation required the usage of code generation or reflection, which should be avoided.
從官方文檔的注釋可以看到,註解要麼依賴反射降低運行時性能,要麼依靠 APT 降低編譯速度,不是完美的方案。
我們之所引入註解,無非是不想多實現幾個空方法。早期 Android 工程不支持 Java8 編譯,接口沒有 default 方法, 現如今 Java8 已經是默認配置,可以為接口添加 default 方法,此時註解已經失去了存在的意義。
如今官方推薦使用 DefaultLifecycleObserver 接口來定義你的 LifecycleObserver
publicinterfaceDefaultLifecycleObserverextendsFullLifecycleObserver{@OverridedefaultvoidonCreate(@NonNullLifecycleOwnerowner){}@OverridedefaultvoidonStart(@NonNullLifecycleOwnerowner){}@OverridedefaultvoidonResume(@NonNullLifecycleOwnerowner){}@OverridedefaultvoidonPause(@NonNullLifecycleOwnerowner){}@OverridedefaultvoidonStop(@NonNullLifecycleOwnerowner){}@OverridedefaultvoidonDestroy(@NonNullLifecycleOwnerowner){}}FullLifecycleObserverAdapter, 無腦回調 FullLifecycleObserver 即可
classFullLifecycleObserverAdapterimplementsGenericLifecycleObserver{privatefinalFullLifecycleObservermObserver;FullLifecycleObserverAdapter(FullLifecycleObserverobserver){mObserver=observer;}@OverridepublicvoidonStateChanged(LifecycleOwnersource,Lifecycle.Eventevent){switch(event){caseON_CREATE:mObserver.onCreate(source);break;caseON_START:mObserver.onStart(source);break;caseON_RESUME:mObserver.onResume(source);break;caseON_PAUSE:mObserver.onPause(source);break;caseON_STOP:mObserver.onStop(source);break;caseON_DESTROY:mObserver.onDestroy(source);break;caseON_ANY:thrownewIllegalArgumentException("ON_ANYmustnotbeensendbyanybody");}}}需要注意 DefaultLifecycleObserver 在 2.4.0 之前也是可以使用的, 存在於 androidx.lifecycle.lifecycle-common-java8 這個庫中, 2.4.0 開始 統一移動到 androidx.lifecycle.lifecycle-common 了 ,已經沒有 java8 單獨的擴展庫了。
END
推薦閱讀
Compose Multiplatform 實戰聯機小遊戲
Jetpack MVVM七宗罪 之一 :還在使用 Fragment 作為 LifecycleOwner ?
面試突擊:OkHttp 原理 8 連問
加好友進交流群,技術乾貨聊不停

