轉(zhuǎn)載請注明出處:
Lifecycle-aware Components google官方生命周期組件
地址:http://www.reibang.com/p/aa6275ad5664
目錄
很多情況下,業(yè)務(wù)模塊需要activity的生命周期,由此會產(chǎn)生很多級聯(lián)耦合恼布。google官方提供了Lifecycle-aware 組件可以幫助我們?nèi)サ暨@種耦合。
1 場景
比如你需要在a模塊中調(diào)用activty的ondestroy()方法踏堡,你肯定會寫一個接口,在業(yè)務(wù)模塊中實現(xiàn)咒劲,然后activity中set進來這個實現(xiàn)顷蟆,在ondestroy()方法中調(diào)用這個實現(xiàn)。這時候你的activity肯定需要耦合a模塊腐魂,使用delegate類帐偎,和這個是一個道理。通過delegate層可以稍微減少這種關(guān)系蛔屹,但如果一個模塊層級較深削樊,我們又想獲取activity 的生命周期,比如onDestroy()中取消訂閱判导,我們還是不得不進行硬性耦合嫉父。
2 更深入的好處
這個功能太棒了沛硅,在框架中眼刃,我們知道我們把view和model綁定后绕辖,我們需要一個觸發(fā)時機來啟動model進行加載數(shù)據(jù),觸發(fā)時機肯定就是activity的onStart()或onCreate()生命周期擂红,因此仪际,我們不得不建立activity和業(yè)務(wù)模塊的硬性耦合,但這個組件做到了不耦合昵骤,這樣我們就不需要傳遞實現(xiàn)/接口树碱,也不需要delegate。
3 用法
- 你需要你的有業(yè)務(wù)模塊實現(xiàn)LifecycleObserver接口变秦,實現(xiàn)的方法可以按需增減(因為使用的是注解的形式成榜,所以你可以只寫你需要的方法):
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void onCreate() {
Log.e("lifecycle","WishScoreRelativeLayout.onCreate()" );
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() {
Log.e("lifecycle","WishScoreRelativeLayout.onStart()");
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
Log.e("lifecycle","WishScoreRelativeLayout.onResume()");
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop() {
Log.e("lifecycle","WishScoreRelativeLayout.onStop()");
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestroy() {
Log.e("lifecycle","WishScoreRelativeLayout.onDestroy()" );
}
- 在這個組件初始化的地方進行:
if (context instanceof LifecycleRegistryOwner){
((LifecycleRegistryOwner) context).getLifecycle().addObserver(this);
}
即使addObserver()的時候activity已經(jīng)進行到了onResume,你在組件中又寫了onCreate(),onStart()的回調(diào)蹦玫,那么在addObserver的時候赎婚,就會執(zhí)行之前的onCreate(),onStart()樱溉。因為addObserver()的時候會判斷activty的生命周期狀態(tài)挣输,然后把之前的生命周期回調(diào)執(zhí)行了。
比如我們讓WishScoreRelativeLayout實現(xiàn)LifecycleObserver中各個生命周期回調(diào)福贞,然后在WishScoreRelativeLayout初始化時期addObserver()撩嚼,初始化時期的時機是MovieDetailBlockActivity的onResume。那么我們看下:
可以看到WishScoreRelativeLayout在addObserver()時挖帘,會先調(diào)用onCreate(),onStart()生命周期的回調(diào),雖然這時候activity已經(jīng)進行到了onResume()完丽。
我們還可以觀察到:
Observer的onCreate(),onStart()拇舀,onResume()是在宿主activity的onCreate()逻族,onStart(),onResume()之后觸發(fā)的你稚,
Observer的onPause()瓷耙,onStop(),onDestroy()是在宿主activity的oonPause()刁赖,onStop()搁痛,onDestroy()之前觸發(fā)的
感興趣的同學,可以看下源碼宇弛,是怎么實現(xiàn)這個特點的鸡典。
-
我們還需要activity實現(xiàn)LifecycleRegistryOwner:
public class MyFragment extends Fragment implements LifecycleRegistryOwner { LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this); @Override public LifecycleRegistry getLifecycle() { return lifecycleRegistry; } }
4 實現(xiàn)原理
你可能會問為什么,實現(xiàn)的機制是什么枪芒?我擼了一遍源碼彻况,有很多小細節(jié)谁尸,設(shè)計的很不錯。但是沒有做筆記纽甘。也不是很難良蛮,自己可以直接看源碼,也可以參考
- https://developer.android.com/topic/libraries/architecture/lifecycle.html
- http://chaosleong.github.io/2017/05/27/How-Lifecycle-aware-Components-actually-works/
當然悍赢,我也可以粗略的講述一下:
核心就是借助lifecycleRegistry做為中介層决瞳,來實現(xiàn)對生命周期事件的發(fā)送和訂閱。對生命周期的訂閱左权,可以很清楚的看到是剛才寫的LifecycleObserver皮胡。那么lifecycleRegistry怎么獲取的activty的生命周期的呢?因為這里借助了
((Application) context.getApplicationContext())
.registerActivityLifecycleCallbacks(activityLifecycleCallback)
在activityLifecycleCallback 中的各個生命周期回調(diào)中進行了LifecycleRegistry.handleLifecycleEvent(特定生命周期event)赏迟。這就是大體的過程屡贺,當然實際上比這復雜的多。比如锌杀,并不是使用的activityLifecycleCallback中的生命周期回調(diào)甩栈,因為這個不準確。那怎么獲取的activity或者是fragment的生命周期的回調(diào)呢抛丽?看過glide源碼的同學肯定知道谤职,glide使用新創(chuàng)建一個fragment來監(jiān)聽宿主activity的生命周期,這里類似亿鲜,也使用新建了一個ReportFragment允蜈,我們監(jiān)聽的是ReportFragment的生命周期回調(diào)(當然這個也不準確,還監(jiān)聽了其他的)蒿柳。對于activityLifecycleCallback饶套,內(nèi)部還賦予一個生命周期狀態(tài)參數(shù),LifecycleRegistry在add這個callback和發(fā)送生命周期event的時候垒探,根據(jù)這個參數(shù)和lifecycleRegistry的狀態(tài)參數(shù)對比妓蛮,進行狀態(tài)的升降來同步他們的狀態(tài)。我們前面看到了LifecycleObserver里面都是注解的方法圾叼,這里還用到了注解處理的一些邏輯蛤克,然后反射生成GenericLifecycleObserver實例,便于以后調(diào)用它的onStateChanged()方法夷蚊。還是挺復雜的构挤,能學到不少東西,可以看看惕鼓。
5 效率和方法數(shù)引入
查看了包大小筋现,這個只會引入25個左右的類,還算是比較輕量級了。并且是官方的library矾飞,所以也不存在第三方包的一些問題一膨。至于效率上,通過上面的原理介紹洒沦,其實就是在activity周期回調(diào)的時候豹绪,會查看注冊這個activity的所有observer,然后通知他們進行回調(diào)微谓。按理說代碼不會多執(zhí)行太多的代碼森篷。在addobserver()上输钩,需要反射實例化GenericLifecycleObserver豺型,可能這點上有些效率的犧牲。