Handling LifeCycle
android.arch.lifecycle 提供的類和接口,讓使用者構建可以感知生命週期。
Lifecycle is a class that holds the information about the lifecycle state of a component (like an activity or a fragment) and allows other objects to observe this state.
根據Activity or fragment的生命週期自行調整類的行爲經過觀察其狀態
Lifecycle uses two main enumerations to track the lifecycle status for its associated component:
AAC 中提供了LifeCycle 使用枚舉類來解決生命週期管理問題。
- 持有Activity/Fragment 生命週期類
- 經過接口LifecycleRegistryOwner /LifecycleObserver 註解事件@OnLifecycleEvent(),以及外部調用觀察者模式addObserver(mTx),來完成將(Activity/Fragment)」生命週期」共享給其餘組件這麼一件事
- 事件
生命週期事件由系統來分發,這些事件對應與Activity和Fragment的生命週期函數
(ON_CREATE,ON_START,ON_RESUME,ON_PAUSE,ON_STOP,ON_DESTROY)
LifeCycle的狀態,用於追蹤lifecycle對象: (INITIALIZED,DESTROYED,CREATED,STARTED,RESUMED)
ps:在STARTED和RESUMED 狀態是處於活躍狀態,只有在這兩個狀態下LivaData是會通知數據變化的。
ps 考慮一個問題:
LifeCycle 是如何感知到Activity或是Fragment的生命週期的呢?
由於AAC是基於MVVM架構的因此首先開一下 MVP和MVVM的感知生命週期操做。
(1)MVP感知生命週期的方法
最開始的attach和detach ,經過Activity或是Fragment中生命週期函數去關聯Presenter,以後判斷View是不是Active的來決定是否更新Ui。由於Retrofit和RxJava的興起,能夠將Presenter中的動做變成一個流事件。經過RxJava特效經過解除訂閱的方式來控制Presenter中的更新Ui的動做。後面有出了RxLifecycle,經過細微控制到每個生命週期函數,更進一步的感知處理每一個生命週期函數。
(2)MVVM感知生命週期的方法
創造一個MVVM ViewModel接口 ,裏面包含全部的生命週期回掉的方法,而後在Aor f中的各個生命週期函數中調用。
(3)官方的MVVM感知生命週期的方法
在《使用ContentProvider初始化你的Library》 一文中,做者提到使用了ContentProvider進行library的初始化,並經過其控制生命週期函數
LifeCycle 源碼分析:
<provider
android:name = 「android.arch.lifecycle.LifecycleRuntimeTrojanProvider"
android:exported = 「fasle」
android:multiporcess = 「true」
android:authoritites = "com.example.hbl.mbbm.lifecycle-trojan"
/>
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public class LifecycleRuntimeTrojanProviderextends ContentProvider {
@Override
public boolean onCreate() {
LifecycleDispatcher .init ( getContext() ); //初始化生命週期控制的方法
ProcessLifecycleOwner.init( getContext() );
return true;
}
}
在LifecycleDispatcher()方法中 又是如何操做的呢?
Class LifecycleDispatcher{
private static final String REPORT_FRAGMENT_TAG = 「android.arch.lifecycle"
+ 「.LifecycleDispatcher.report_fragment_tag」 ;
private static AtomicBooleansInitialized= new AtomicBoolean ( false);
static void init (Context context) {
if(sInitialized .getAndSet (true) ){
return ;
}else {
( (Application)context .getApplicationContext() ). registerActivityLifecycleCallbacks
(new DispatcherActivityCallback());
}
}
解析:經過AtomicBoolean來控制初始化一次,以後獲取ApplicationContext並設置ActivityLifecycleCallback回調。
ps:AtomicBoolean 函數在退出app的時候能夠用到
在DispatcherActivityCallback中:
在DispatcherActivityCallback()構造函數中
一、建立了一個FragmentCallback對象,用於設置Fragment的生命週期。
二、在onActivityCreated()函數中 instanceof 一個FragmentActivity,注入一股ReportFragment到當前Activity
三、在ReportFragment中,將這個Fragment 添加到當前Activity中,讓當前的fragment綁定到Activity的生命週期中
四、以後經過onActivityCreate()函數中的dispatch()方法把當前生命週期分發到對應的LifecycleOwner中
五、經過這種方法,給Activity or Fragment添加其餘額外的fragment,來獲取當前的Activity 或是Fragment的生命週期。而後判斷當前的Activity 或是Fragment是不是LifeCycleRegistryOwner的。若是是,那麼就分發當前的生命週期事件到當前的Owner中,以達到生命週期的傳遞操做
(一)建立監聽器
classMyLocationListener{
publicMyLocationListener(Contextcontext,Callbackcallback){
// ...
}
voidstart(){
// connect to system location service
}
voidstop(){
// disconnect from system location service
}
}
在須要的Activity中綁定監聽器
privateMyLocationListenermyLocationListener;
@Override
publicvoidonCreate(...){
myLocationListener =newMyLocationListener(this,(location)->{
// update UI
});
}
@Override
publicvoidonStart(){
super.onStart();
myLocationListener.start();
// manage other components that need to respond
// to the activity lifecycle
}
@Override
publicvoidonStop(){
super.onStop();
myLocationListener.stop();
// manage other components that need to respond
// to the activity lifecycle
}
(二)建立觀察者對象
publicclassMyObserverimplementsLifecycleObserver{
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
publicvoidconnectListener(){
...
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
publicvoiddisconnectListener(){
...
}
}
myLifecycleOwner.getLifecycle().addObserver(newMyObserver());
(三)實現LifeCycleOwner 綁定Activity或是Fragment生命週期
publicclassMyActivityextendsActivityimplementsLifecycleOwner{
privateLifecycleRegistrymLifecycleRegistry;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
mLifecycleRegistry =newLifecycleRegistry(this);
mLifecycleRegistry.markState(Lifecycle.State.CREATED);
}
@Override
publicvoidonStart(){
super.onStart();
mLifecycleRegistry.markState(Lifecycle.State.STARTED);
}
@NonNull
@Override
publicLifecyclegetLifecycle(){
returnmLifecycleRegistry;
}
}
一、定義一個類實現LifeCycleObserver方法
二、定義2個狀態變量
三、自定義類實現LifecycleObserver接口,並添加Lifecycle的生命週期綁定註解
class MyView extends TextView implements LifecycleObserver{
private boolean lifeCycleEnable;
private Lifecycle lifecycle;
//添加構造方法
public boolean isLifeCycleEnable() {
return lifeCycleEnable;
}
public void setLifeCycleEnable(boolean lifeCycleEnable) {
this.lifeCycleEnable = lifeCycleEnable;
}
public Lifecycle getLifecycle() {
return lifecycle;
}
// ****************** lifeCycle 生命週期函數事件******************
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void create() {
if (lifeCycleEnable) {
String text = System.currentTimeMillis() + "-create/n";
Log.i(TAG, text);
this.setText(text);
}
}
//同理Lifecycle.Event.ON_其餘事件 ON_START 、ON_PAUSE、ON_STOP、ON_RESUME、ON_DESTROY、ON_ANY
}
在Activity中的使用:
publicclass XActivity extends AppCompatActivity implements LifecycleRegistryOwner {
privateLifecycleRegistry lifecycleRegistry =newLifecycleRegistry(this);
//在onCreate()函數中初始化控件 mtx
mtx .setLifecycle(getLifecycle());
//lifecycle觀察者 LifecycleObserver:自定義的類 MyView
//lifecycle註冊擁有者 LifecycleRegistryOwner:XActivity
getLifecycle().addObserver(mtx); //添加觀察者角色
mtx .setLifeCycleEnable(true);
@Override
public LifecycleRegistry getLifecycle() {
return lifecycleRegistry;
}
}
按home鍵進行觀察日誌:
creat -> start -> resume -> pause -> stop -> start -> resume
02-24 16:18:31.188 4694-4694/proxy.lifecycledemo E/MyView: Hello World!-creat
02-24 16:18:31.198 4694-4694/proxy.lifecycledemo E/MyView:-start
02-24 16:18:31.198 4694-4694/proxy.lifecycledemo E/MyView:-resume
02-24 16:32:46.058 4694-4694/proxy.lifecycledemo E/MyView:-pause
02-24 16:32:46.798 4694-4694/proxy.lifecycledemo E/MyView:-stop
02-24 16:32:47.988 4694-4694/proxy.lifecycledemo E/MyView:-start
02-24 16:32:47.988 4694-4694/proxy.lifecycledemo E/MyView:-resume
解析:LifecycleOwner是一個只有一個方法的接口getLifecycle(),須要由子類來實現。
在Lib中已經有實現好的子類,咱們能夠直接拿來使用。好比LifecycleActivity和LifecycleFragment,咱們只須要繼承此類就好了。
固然實際開發的時候咱們會本身定義BaseActivity,Java是單繼承模式,那麼須要本身實現LifecycleRegistryOwner接口。
以下所示便可,代碼很近簡單
public class BaseFragment extends Fragment implements LifecycleRegistryOwner {
LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);
@Override
public LifecycleRegistry getLifecycle() {
return lifecycleRegistry;
}
}
Lifecycle的最佳建議
- 保持UI Controllers(Activity/Fragment)中代碼足夠簡潔。必定不能包含如何獲取數據的代碼,要經過ViewModel獲取LiveData形式的數據。
- 用數據驅動UI,UI的職責就是根據數據改變顯示的內容,而且把用戶操做UI的行爲傳遞給ViewModel。
- 把業務邏輯相關的代碼放到ViewModel中,把ViewModel當作是連接UI和App其餘部分的膠水。但ViewModel不能直接獲取數據,要經過調用其餘類來獲取數據。
- 使用DataBinding來簡化View(佈局文件)和UI Controllers(Activity/Fragment)之間的代碼
- 若是佈局自己太過複雜,能夠考慮建立一個Presenter類來處理UI相關的改變。雖然這麼作會多寫不少代碼,可是對於保持UI的簡介和可測試性是有幫助的。
- 不要在ViewModel中持有任何View/Activity的context。不然會形成內存泄露。