Android Architecture Components 系列(二) LifeCycle


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()構造函數中
1、創建了一個FragmentCallback對象,用於設置Fragment的生命周期。
2、在onActivityCreated()函數中 instanceof 一個FragmentActivity,注入一股ReportFragment到當前Activity
3、在ReportFragment中,將這個Fragment 添加到當前Activity中,讓當前的fragment綁定到Activity的生命周期中
 
4、之后通過onActivityCreate()函數中的dispatch()方法把當前生命周期分發到對應的LifecycleOwner中
5、通過這種方法,給Activity or Fragment添加其他額外的fragment,來獲取當前的Activity 或是Fragment的生命周期。然后判斷當前的Activity 或是Fragment是否是LifeCycleRegistryOwner的。如果是,那么就分發當前的生命周期事件到當前的Owner中,以達到生命周期的傳遞操作
 
  • 官方LifeCycle的使用案例:
(一)創建監聽器
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;
    }
}
 
  • 一個有關LifeCycle 的小Ex:
    1、定義一個類實現LifeCycleObserver方法 
    2、定義2個狀態變量 
    3、自定義類實現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。否則會造成內存泄露。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM