Lifecycle
Lifecycle 是 Android Architecture Components 的一個(gè)組件平斩,用于將系統(tǒng)組件(Activity灭必、Fragment等等)的生命周期分離到 Lifecycle
類排宰,Lifecycle
允許其他類作為觀察者叁征,觀察組件生命周期的變化壶辜。Lifecycle 用起來很簡(jiǎn)單贰盗,首先聲明一個(gè) LifecycleObserver
對(duì)象薛窥,用 @OnLifecycleEvent
注解聲明生命周期事件回調(diào)的方法:
public class LifecycleObserverDemo implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_ANY)
void onAny(LifecycleOwner owner, Lifecycle.Event event) {
System.out.println("onAny:" + event.name());
}
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
void onCreate() {
System.out.println("onCreate");
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
void onDestroy() {
System.out.println("onDestroy");
}
}
然后在 LifecycleRegistryOwner
比如 LifecycleActivity
加入這么一行代碼:
getLifecycle().addObserver(new LifecycleObserverDemo());
然后?然后就沒了儒飒,運(yùn)行起來可以看到 LifecycleActivity
的生命周期發(fā)生變化時(shí),LifecycleObserverDemo
總能得到通知檩奠。而 LifecycleActivity
只有寥寥幾行代碼桩了,并沒有覆蓋任何回調(diào)方法。那么 Lifecycle 是怎么做到的埠戳,是不是有點(diǎn)黑魔法的感覺井誉?
注解的作用
首先從注解入手,可以在 build 目錄下發(fā)現(xiàn)注解處理器為我們生成了 LifecycleObserverDemo_LifecycleAdapter
整胃,不過這只是一個(gè)適配器颗圣,用于將生命周期事件派發(fā)到 LifecycleObserverDemo
對(duì)應(yīng)的方法。
public class LifecycleObserverDemo_LifecycleAdapter implements GenericLifecycleObserver {
final LifecycleObserverDemo mReceiver;
LifecycleObserverDemo_LifecycleAdapter(LifecycleObserverDemo receiver) {
this.mReceiver = receiver;
}
@Override
public void onStateChanged(LifecycleOwner owner, Lifecycle.Event event) {
mReceiver.onAny(owner,event);
if (event == Lifecycle.Event.ON_CREATE) {
mReceiver.onCreate();
}
if (event == Lifecycle.Event.ON_START) {
mReceiver.onStart();
}
if (event == Lifecycle.Event.ON_PAUSE) {
mReceiver.onPause();
}
if (event == Lifecycle.Event.ON_DESTROY) {
mReceiver.onDestroy();
}
}
public Object getReceiver() {
return mReceiver;
}
}
如何傳達(dá) lifecycle 事件
注解也沒有生成任何相關(guān)的代碼屁使,而 Activity 不用寫任何代碼在岂,那么 Lifecycle 是如何把 Activity 生命周期事件傳遞給 LifecycleObserver
的?
最終通過研讀 Lifecycle 的代碼蛮寂,發(fā)現(xiàn)里面有個(gè)包可見的類 LifecycleDispatcher
蔽午,LifecycleDispatcher
是一個(gè)單例,在 LifecycleDispatcher#init(Context)
中酬蹋,它通過 registerActivityLifecycleCallbacks
方法及老,向當(dāng)前的 Application 注冊(cè)一個(gè) DispatcherActivityCallback
,但 Lifecycle 并沒使用 ActivityLifecycleCallbacks
來監(jiān)聽并派發(fā)生命周期事件范抓。
static void init(Context context){
...
((Application)context.getApplicationContext()).registerActivityLifecycleCallbacks(new LifecycleDispatcher.DispatcherActivityCallback());
...
}
static class DispatcherActivityCallback extends EmptyActivityLifecycleCallbacks {
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
...
if(manager.findFragmentByTag("android.arch.lifecycle.LifecycleDispatcher.report_fragment_tag") == null) {
manager.beginTransaction().add(new ReportFragment(), "android.arch.lifecycle.LifecycleDispatcher.report_fragment_tag").commit();
manager.executePendingTransactions();
}
}
}
而是通過一個(gè)無 UI 的 Fragment骄恶,在 DispatcherActivityCallback#onActivityCreated
可以看到它在 Activity#onCreate
時(shí),為 Activity 添加一個(gè) ReportFragment
匕垫。最終由 ReportFragment
來監(jiān)聽各個(gè)生命周期事件僧鲁,然后傳遞給 LifecycleRegistry
。
public class ReportFragment extends Fragment {
...
public void onPause() {
super.onPause();
dispatch(Event.ON_PAUSE);
}
...
private void dispatch(Event event) {
if(this.getActivity() instanceof LifecycleRegistryOwner) {
((LifecycleRegistryOwner)this.getActivity()).getLifecycle().handleLifecycleEvent(event);
}
}
}
Activity 的生命周期事件都會(huì)派發(fā)到它的 Fragments年缎,向 Activity 注冊(cè)一個(gè)無 UI 的 Fragment 也叫 Headless Fragment 用于將各種 Activity 回調(diào)分離出來是個(gè)常用的做法悔捶,比如 RxPermissions 也是用這種方法來避免復(fù)寫 Activity#onRequestPermissionsResult
。
順便一提 Lifecycle 文檔提到:
ON_CREATE, ON_START, ON_RESUME events in this class are dispatched after the LifecycleOwner's related method returns. ON_PAUSE, ON_STOP, ON_DESTROY events in this class are dispatched before the LifecycleOwner's related method is called.
正好是 Fragment 生命周期回調(diào)的觸發(fā)順序单芜。
Activity
的生命周期變化是如何傳遞到 LifecycleObserver
有了清晰的圖表:
LifecycleRuntimeTrojanProvider
還有一個(gè)問題蜕该, LifecycleDispatcher#init(Context)
并不是入口,它也需要被調(diào)用洲鸠。那么他的調(diào)用者是誰堂淡?Google 這里的做法還是很巧妙的馋缅,如果這時(shí)把 apk 的 AndroidManifest.xml 提取出來,就會(huì)發(fā)現(xiàn)多了一個(gè) ContentProvider 聲明:
<provider
android:name="android.arch.lifecycle.LifecycleRuntimeTrojanProvider"
android:authorities="${applicationId}.lifecycle-trojan"
android:exported="false"
android:multiprocess="true" />
LifecycleRuntimeTrojanProvider
绢淀,運(yùn)行時(shí)木馬是什么鬼萤悴?實(shí)際上,它不是一個(gè) ContentProvider皆的,而是利用 ContentProvider 的特點(diǎn)在應(yīng)用程序初始化時(shí)覆履,向其注入兩行代碼:
LifecycleDispatcher.init(getContext());
ProcessLifecycleOwner.init(getContext());
這里 ContentProvider 之于 Application 的作用就類似于 Headless Fragment 之于 Activity 一樣,目的都是避免繼承系統(tǒng)組件费薄。關(guān)于 ContentProvider 的生命周期可以看 android - ContentProvider destruction/lifecycle - Stack Overflow硝全,
其他 LifecycleOnwer
最后再提一下,Lifecycle 還提供了內(nèi)置了另外三個(gè) LifecycleOnwer:
- LifecycleFragment
- LifecycleService楞抡,ServiceLifecycleDispatcher 將事件派發(fā)重新推到主線程消息隊(duì)列伟众,用于保證確保回調(diào)在 Service 生命周期回調(diào)后再調(diào)用召廷。
- ProcessLifecycleOwner凳厢,用于監(jiān)聽整個(gè)應(yīng)用的前后臺(tái)切換。也是利用 ActivityLifecycleCallback 監(jiān)聽每個(gè) Activity 的生命周期竞慢,如果 onStop 事件后先紫,沒有監(jiān)聽到任意的 onStart 事件,那么 ProcessLifecycleOwner 就會(huì)認(rèn)為整個(gè)應(yīng)用切換到后臺(tái)梗顺,同時(shí)留下一個(gè)標(biāo)志泡孩。如果監(jiān)聽到 onStart 事件,同時(shí)檢查有標(biāo)志那么就會(huì)認(rèn)為應(yīng)用回到前臺(tái)寺谤。
Lifecycle 的應(yīng)用仑鸥?
有朋友在問 Lifecycle 有什么應(yīng)用。我覺得 Lifecycle 最主要的作用就是在于解耦变屁。以前我們使用一個(gè)生命周期敏感的模塊 m眼俊,必須得在 Activity 子類里面添加類似下面的代碼
super.onCreate()
m.init()
m.release()
super.onDestory()
這類組件之多,用起來之頻繁粟关。以致于我們經(jīng)常要?jiǎng)?chuàng)建一個(gè) BaseActivity
類來做這些臟活疮胖。不過,一旦我們建立了BaseActivity
闷板,我們常常就能體會(huì)到 Java 單繼承之痛澎灸。Activity不止一個(gè)啊:
-
LifecycleActivity
遮晚、 -
AppcompatActivity
性昭、 FragmentActivity
- 等等…
還有第三方庫的,比如 CordovaActivity
… 县遣。隨著項(xiàng)目的擴(kuò)大糜颠,你很難只用一類 Activity汹族。而且有生命周期的組件不止一個(gè),這些組件的子類也花樣繁多其兴,我們建立了 BaseFragment
顶瞒、BaseService
…同時(shí)也建立了更多痛苦。為什么我們的模塊要和這些復(fù)雜性綁定在一起元旬?生命周期敏感模塊應(yīng)該與獨(dú)立起來榴徐,變成一個(gè)可以在任意有生命周期的組件安裝的模塊,所以 Lifecycle 就在幫我們做這種事情法绵。
getLifecycle().addObserver(new LifecycleObserverDemo());
那么具體一點(diǎn)這類生命周期敏感的組件有哪些呢箕速?官方以 LocationManager 為例,主要作用避免 Activity 遁入后臺(tái)后繼續(xù)定位浪費(fèi)電量朋譬。這里我以 volley 為例,舉一個(gè)網(wǎng)絡(luò)請(qǐng)求經(jīng)常要面對(duì)的問題:
volleyClient.query(new Respose.Listener(){});
上面的代碼是個(gè)老生常談的問題了兴垦,new Respose.Listener(){}
是 Activity 的一個(gè)匿名類徙赢,它有指向 Activity 的引用,而 Volley 是一個(gè)存活范圍比 Activity 更大的實(shí)例探越,比如常常 VolleyClient 就是單例狡赐。這就導(dǎo)致了 Activity 銷毀后不能及時(shí)釋放,內(nèi)存泄漏钦幔!當(dāng)然枕屉,網(wǎng)絡(luò)請(qǐng)求終會(huì)返回的,這個(gè)回調(diào)對(duì)象就會(huì)被銷毀鲤氢,從這個(gè)角度講搀擂,問題也不是很大。另外一個(gè)就是請(qǐng)求返回的時(shí)候卷玉,我們會(huì)在 onSuccess 里操作 UI哨颂,如果 Activity 已經(jīng)銷毀了,沒做檢查的話那么就會(huì)崩潰相种。這些都不是大問題威恼,但是很煩人。所以像 volley 請(qǐng)求這樣的就是一個(gè)生命周期敏感的功能寝并。
網(wǎng)絡(luò)請(qǐng)求和定位回調(diào)一樣都可以歸類為生命周期敏感的數(shù)據(jù)源箫措,Google 為這種類型的數(shù)據(jù)源提供了 LiveData。這就是 LifecycleObserver 一個(gè)典型的應(yīng)用衬潦,當(dāng)然這只是 LiveData 的一部分功能斤蔓。
非數(shù)據(jù)源的生命周期敏感組件,比如說用戶行為收集模塊别渔,它本身就是一個(gè)生命周期的監(jiān)聽者附迷,在沒有 ActivityLifecycleCallback
的年代(API<14)惧互,常常需要在各個(gè) Activity 中手動(dòng)加入開始記錄和停止紀(jì)錄的代碼。有了 ActivityLifecycleCallback
之后喇伯,我們需要做的就變成在 Application#onCreate
加一句代碼喊儡。那么現(xiàn)在把用戶行為收集模塊變成 LifecycleObserver
有什么好處?
很遺憾稻据,對(duì)于這個(gè)例子我暫時(shí)還想不出有什么特別好的地方艾猜,但是它能說明 LifecycleObserver 一個(gè)最主要的特點(diǎn)。比如我們有十個(gè) Activity捻悯,只有 Activity1 和 Activity2 需要記錄匆赃,那么用 LifecycleObserver 就可以避免用配置去聲明哪些 Activity 需要記錄。直接在需要記錄的 Activity加入如下代碼
getLifecycle().addObserver(new OpRecorder());
這就是解耦的好處今缚。能讓一個(gè)與生命周期深度耦合的組件變成一個(gè)隨處可安裝的組件算柳。
最后,還是要回到這篇文章的主題姓言,我們從 Lifecycle 的代碼可以學(xué)到一個(gè)更大的模式瞬项。
Activity 不只有生命周期回調(diào),還有權(quán)限何荚,onActivityResult 等等囱淋。那些需要與這些回調(diào)深度耦合的模塊,利用 Lifecycle 用的技術(shù) Headless Fragments 來解耦是個(gè)不錯(cuò)的方法餐塘。對(duì)于整個(gè) Application 來說那就可以用更 tricky 的 Headless ContentProvider妥衣。