橫向對比Jetpack、RxJava、Glide框架中對組件生命週期Lifecycle感知原理

前言

在App開發中出於減小內存泄露,合理釋放資源,減小內存佔用等目的,咱們常常要在組件的生命週期回調函數中執行相應的代碼好比像這樣:java

class xxActivity extend Activity{
    public void onStart(){
        xxx.init()
    }
    public void onStop(){
        xxx.stop();
    }
    public void onDestoryt(){
       xxx.clean();
    }
}
複製代碼

能解決問題但不夠優雅,耦合度過高,咱們看看咱們常用的那些優秀的框架是怎樣來處理這個問題的。android

一、Glide中的Lifecycle

使用Glide.with()一系列的重載方法,最終經過組織的圖片請求就能感知組件生命週期並作出響應處理。他是怎麼作到的呢?git

1.一、RequsetManagerRetriever相關代碼

public static RequestManager with(@NonNull Activity activity) {
    return getRetriever(activity).get(activity);
  }
複製代碼
  • Glide.with(xxx)轉交都轉交給了RequsetManagerRetriever的一系列get()重載方法;最終返回一個RequestManager對象
  • 在RequestManagerRetriever中獲取到RequestManager是經過一系列的get()重載方法,get()方法的參數能夠是Fragment、SupportFragment、Activity、SupportActivity、View或者Context。最終的目的都是儘量經過這些組件中獲取出FragmentManager。以參數爲Activity爲例代碼以下:
public RequestManager get(@NonNull Activity activity) {
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
      //在Activity中獲取到FragmentManager
      android.app.FragmentManager fm = activity.getFragmentManager();
      return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }
複製代碼

1.二、獲取到RequestManager

經過這些方法獲取或者建立Fragmentgithub

@NonNull
  private RequestManager supportFragmentGet(
      @NonNull Context context,
      @NonNull FragmentManager fm,
      @Nullable Fragment parentHint,
      boolean isParentVisible) {
    SupportRequestManagerFragment current =
        getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      // TODO(b/27524013): Factor out this Glide.get() call.
      Glide glide = Glide.get(context);
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }
複製代碼
  • 使用getSupportRequestManagerFragment()方法獲的SupportRequestManagerFragment。
  • 若是是第一次,建立RequestManager,並設置設置給SupportRequestManager。若是不是第一次,直接從SupportRequestManagerFragment中獲取。
  • 返回RequestManager對象

1.三、 SupportRequestManager的構建

...
 final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments =
      new HashMap<>();
...
  @NonNull
  private SupportRequestManagerFragment getSupportRequestManagerFragment(
      @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
      //在Fragment中找ManagerFragment
    SupportRequestManagerFragment current =
        (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        
    if (current == null) {
    //若是在沒找到,就在存儲的map中嘗試獲取
      current = pendingSupportRequestManagerFragments.get(fm);
      if (current == null) {
      //沒有就建立新的。
        current = new SupportRequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        if (isParentVisible) {
          current.getGlideLifecycle().onStart();
        }
        pendingSupportRequestManagerFragments.put(fm, current);
        //移除
        handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }
複製代碼

如註釋中所言,bash

  • 若是FragmentManager中不存在tag爲FRAGMENT_TAG而後返回
  • 簡而言之,RequestManagerTreeNode用來獲取綁定該RequestManagerFragment的Fragment的全部子Fragment所綁定的RequestManagerFragment所綁定的RequestManager
  • 值得注意在FragmentManager中沒有發現TAG爲fragement_tag的時候會從pendingSupportRMF中獲取若是沒有就建立新的而後先將新建立的RMF放入pendingSupportRM中而後執行添加transaction緊接着經過handler又將RMF從pendingSupportRM中移除了,思考,爲何? 由於
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
複製代碼

這個操做是異步的!什麼概念就是試想:這樣的狀況網絡

public test(){
    Glide.with(activity).load("xxx1").into(target1);//1
    Glide.with(activity).load("xxx1").into(target2);//2
}
複製代碼

代碼1和代碼2被調用假設當前的activity尚未RequestManagerFragemnt,必然就會執行去建立的流程,代碼1執行到了 pendingSupportRequestManagerFragments.put(fm, current);異步去添加,也就是使用handler將整個添加操做包裝成了Message發送到了主線程的Looper中的messageQueue中而不是當即執行會等到Looper.looper()中遍歷到它而後交給他的handler去處理他。異步添加在RFM沒有添加到Activity中的時候,而後代碼2就執行了一樣也Activity中沒有RFM也會去建立,這樣就會在同一Activity中有兩個RequesManagerFragment就出事了,因此引入了pendingSupportRequestManagerFragments,保證不會有上述狀況的發生。向Activity中添加RFM這個異步任務以後,向Handler發送移除從pendingSupportRequestManagerFragments移除,這樣就保證,在添加成功以前,都能在pendingSupportRequestManagerFraments中獲取到RFM。數據結構

1.四、SupportRequestManagerFragment

public class SupportRequestManagerFragment extends Fragment {

  private final ActivityFragmentLifecycle lifecycle;
  private final RequestManagerTreeNode requestManagerTreeNode = ...
  @Nullable private SupportRequestManagerFragment rootRequestManagerFragment;
  @Nullable private RequestManager requestManager;
    ...
  public SupportRequestManagerFragment() {
    this(new ActivityFragmentLifecycle());
  }
  ActivityFragmentLifecycle getGlideLifecycle() {
    return lifecycle;
  }
  ...
  private void addChildRequestManagerFragment(SupportRequestManagerFragment child) {
    childRequestManagerFragments.add(child);
  }

  private void removeChildRequestManagerFragment(SupportRequestManagerFragment child) {
    childRequestManagerFragments.remove(child);
  }
    ...
    ...
  @Override
  public void onAttach(Context context) {
    super.onAttach(context);
      registerFragmentWithRoot(getActivity());
  }

  @Override
  public void onDetach() {
    super.onDetach();
    unregisterFragmentWithRoot();
  }
  ...
複製代碼
  • RequestManagerFragment在構造函數中默認建立一個ActivityFragmentLifecycle類型的成員變量。
  • 在attach中registerFragmentWithRoot(),在onDetach()中unregisterFragmentWithRoot();
  • 在RequestManagerFragment的對象中onStart(),onStop,中調用Lifecycle的響應函數
  • 在RequestManager當中會向ActivityFragmentLifecycle註冊監聽對象,因而RequestManager就會對組件生命週期作出相應的反應。
  • 另外當該Fragment做爲一個子Fragment被添加到Fragment當中感知Fragment時,涉及到子Fragment管理可參考

1.五、RequestManager對Activity/Fragment生命週期感知

public class RequestManager implements LifecycleListener
  protected final Glide glide;
  protected final Context context;
  final Lifecycle lifecycle;
  private final RequestTracker requestTracker;
  ...
  RequestManager(...) {
	...
	//RequestManager將自身註冊到Lifecycle中也就是RequestManagerFragment中的Lifecycle
    lifecycle.addListener(this);
    lifecycle.addListener(connectivityMonitor);
	  }
  public synchronized boolean isPaused() {
    return requestTracker.isPaused();
  }
  public synchronized void pauseRequests() {
    requestTracker.pauseRequests();
  }
  public synchronized void pauseAllRequests() {
    requestTracker.pauseAllRequests();
  }
  public synchronized void resumeRequests() {
    requestTracker.resumeRequests();
  }
  //相應的生命週期函數中使用處理土拍你請求
  @Override
  public synchronized void onStart() {
    resumeRequests();
    targetTracker.onStart();
  }
  @Override
  public synchronized void onStop() {
    pauseRequests();
    targetTracker.onStop();
  }
  //在onDestoty中取消解除綁定釋放請求中的設計的資源
  @Override
  public synchronized void onDestroy() {
    targetTracker.onDestroy();
    targetTracker.clear();
    requestTracker.clearRequests();
    lifecycle.removeListener(this);
	...
    glide.unregisterRequestManager(this);
  }
}
複製代碼
  • RequestManager實現了LifecycleListener,且建立的時候傳入了Lifecycle參數賦值給成員變量。
  • 被該RequestManager管理的請求都存放在RequestTracker對象這個成員變量屬性中。
  • RequestManager經過Lifecycle感知組件生命週期變化,在相應的生命週期狀態下實現的LifecyleListener對應的回調函數會被執行,而後經過RequestTracker管理本身所關聯的Request對象們。

Glide中Lifecycle小結

爲一個Request擁有所在組件的感知能力須要如下步驟:
1.從給定的組件(Fragment/FragmentActivity/Activity...)獲取出FragmentManager。

2.建立一個不帶界面的Fragment(SupportRequestManagerFragment/RequestManagerFragment),這個不帶界面的Frament有個Lifecycle成員變量,在Fragment建立的時候被初始化,用於監聽此Fragment的生命週期。app

3.將不帶界面的Frament添加進給定組件。框架

4.建立RequestManager,RequestManager實現了LifecycleListener,建立的時候會傳入無界面fragment中成員Lifecyle,RequestManager會把本身註冊到Lifecycle中,這樣RequestManager就擁有了感知組件生命週期的能力。異步

二、RxLifecycle

對RxLifecycle原理分析主要是依據trello的RxLifecycle,github傳送門點這裏

2.一、簡單使用

在Activity中使用爲例,主要是使用如下兩個方法:

bindUntilEvent(@NonNull ActivityEvent event)

bindToLifecycle()
複製代碼

使用的姿式是這樣的:當Activity 回調onDestory生命週期函數的時候,就會解除訂閱。

Observable.interval(1, TimeUnit.SECONDS)
                .compose(bindUntilEvent(ActivityEvent.DESTROY))
                .subscribe();
複製代碼

2.二、RxActivity構成

追根溯源看看 要先理解Rxjava2中compose()操做符的含義 compose操做符是在不破壞rxjava流式基礎上把當前的Observable轉換爲另外一個Observable,傳入的是一個Transformer對象使用。更爲詳細的關於這個操做符的介紹點這

public abstract class RxActivity extends Activity implements LifecycleProvider<ActivityEvent> {

    private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
    @CheckResult
    public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {
        return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
    }

    public final <T> LifecycleTransformer<T> bindToLifecycle() {
        return RxLifecycleAndroid.bindActivity(lifecycleSubject);
    }

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        lifecycleSubject.onNext(ActivityEvent.CREATE);
    }
    ....
    ....
    protected void onDestroy() {
        lifecycleSubject.onNext(ActivityEvent.DESTROY);
        super.onDestroy();
    }
}
複製代碼
  • Activity中有個一個BehaviorSubject的成員變量:lifecycleSubject。BehaviorSubject會發送離訂閱最近的上一個值,當沒有最近值的的時候會發送默認值。
  • bindUntilEvent(ActivityEvent avt)最終會返回一個Transformer做爲compose()方法的參數。
  • bindUtliEvent方法是RxActivity實現了LifecycleProvider接口的方法,他的實現轉交到了RxLifecycle.bindUntilEvent()

2.3 LifecycleTransformer構建

關於Transformer構建在RxlifeCycle類中主要是如下三個方法:

@CheckReturnValue
    public static <T, R> LifecycleTransformer<T> bindUntilEvent(@Nonnull final Observable<R> lifecycle,@Nonnull final R event) {
        ...判空
        return bind(takeUntilEvent(lifecycle, event));
    }
複製代碼

使用filter()操做符,獲取一個過濾出傳入的指定事件,其餘事件不向下游分發的Observer,也就是隻發送指定事件的Observable。

private static <R> Observable<R> takeUntilEvent(final Observable<R> lifecycle, final R event) {
        return lifecycle.filter(new Predicate<R>() {
            @Override
            public boolean test(R lifecycleEvent) throws Exception {
                return lifecycleEvent.equals(event);
            }
        });
複製代碼

將上一步獲得的Observable實際上是一個BehaviorSubject,當作構造參數傳入LifecycleTransformer

public static <T, R> LifecycleTransformer<T> bind(@Nonnull final Observable<R> lifecycle) {
        return new LifecycleTransformer<>(lifecycle);
    }
複製代碼

2.4 LifecycleTransformer原理

看看LifecyclerTranformer裏賣的啥藥

public final class LifecycleTransformer<T> implements ObservableTransformer<T, T>,
                                                      FlowableTransformer<T, T>,
                                                      SingleTransformer<T, T>,
                                                      MaybeTransformer<T, T>,
    ...
   @Override
    public ObservableSource<T> apply(Observable<T> upstream) {
        return upstream.takeUntil(observable);
    }
    ...                                       
                                                          
}
複製代碼

真相大白,對upstream也就是咱們使用時,xxx.compose()時的那個Observerable進行了takeUtil()操做。 takeUtil的語義是


Returns an Observable that emits the items emitted by the source Observable until a second ObservableSource emits an item. 返回一個發送事件的觀察源,直到第二個被觀察者發送數據。

綜上 當給被觀察序列compose了Transformer對象後,會在相應的生命週期函數中終止。

2.5 小結

  • Activity中有個BehaviorSubject 在Activity的生命週期回調函數中發送向其發送相應的事件。
  • 主要原理就是經過LifecycleProvider的bindUtilEvent方法構建LifecycleTransformr;
  • LifecycleTransformer裏面的apply操做就是將Observable進行TakeUtil操做。這個操做的效果就是中斷上游Observerable的發送Observer取消。好比調用了bindUtilEvent(DESTORY_EVENT)也就是當原始的Observer接收到Event事件的時候就會取消解除Observer監聽。

三、Jetpack Lifecycle

3.一、SupportActivity中對Lifecycle支持

SupportActivity類實現了LifecycleOwner結構

  • Activity onCreate方法中調用了ReportFragment的injectIfNeedIn()方法
public class SupportActivity extends Activity implements LifecycleOwner {
    private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ReportFragment.injectIfNeededIn(this);
    }
  public Lifecycle getLifecycle() {
        return this.mLifecycleRegistry;
    }
複製代碼
  • SupportActivity實現了LifecleOwner接口,這個接口只有一個方法geLifecycle();
  • SupportActivity對這個接口的實現就是返回他的成員變量,LifecycleRegistry類型的成員變量。

3.二、ReportFragment生命週期變動

具備感知所在組件的能力在相應的生命週期回調函數裏向LifecycleRegistry分發事件。

# ReportFragment
  public static void injectIfNeededIn(Activity activity) {
        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
            //當即執行拒絕異步
            manager.executePendingTransactions();
        }
    }
    
    private void dispatch(Lifecycle.Event event) {
        Activity activity = getActivity();
        if (activity instanceof LifecycleRegistryOwner) {
            ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
            return;
        }
        /**2**/
        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
            }
        }
    }
複製代碼

註釋2處

  • 若是Activity實現了LifecyclerOwener,LifecycleOwner接口中方法就是返回一個Lifecycle。
  • Lifecycle的實現類LifecycleRegistry,LifecycleRegistry負責管理和分發生命週期狀態。
  • manager.executePendingTransactions();表示當即執行,transaction是異步的。FragmentManager的Transaction是異步執行了,若是想要當即執行就使用commitNow他表示當前的commit直接執行;executePendingTransactions()會將全部pending在隊列中還有你新提交的transactions都執行了。

3.三、處理生命週期事件LifecycleRegistry

先來一張官方的圖

image

Jetpack對組件生命週期的管理有兩個核心的概念事件(Event)和狀態(State)。 他們直接的關係是事件驅動狀態的轉換

一共有五種狀態,五種狀態之間是怎樣經過事件驅動的方式實現轉換的呢,如上圖所示,

  • INITIALIZED:這是一種初始狀態。。
  • DESTROYED :死亡狀態,ON_DESTORY事件驅動進入這種狀態。
  • CREATED :建立狀態,ON_CREATE事件和STOP事件驅動進入這種狀態,ON_STOP事件驅動離開這種狀態。
  • STARTED : 開始狀態,On_START事件和ON_PAUSE事件驅動進出該種狀態,ON_RESUME和ON_STOP驅動離開該種狀態。
  • RESUME:ON_RESUME事件驅動進入該種狀態,ON_PAUSE事件驅動離開這種狀態。

圖看百遍其意自現,其實當咱們得知某種事件以後就能準確的得知出他將進入的狀態體現就是在LifecycleRegistry的getStateAfter()方法中,就不用文字描述了很代碼很能說明問題。

static State getStateAfter(Event event) {
        switch (event) {
            case ON_CREATE:
            case ON_STOP:
                return CREATED;
            case ON_START:
            case ON_PAUSE:
                return STARTED;
            case ON_RESUME:
                return RESUMED;
            case ON_DESTROY:
                return DESTROYED;
            case ON_ANY:
                break;
        }
        throw new IllegalArgumentException("Unexpected event value " + event);
    }

複製代碼

LifecycleRegistry實現了Lifecyle抽象類,是生命週期監聽者和分發生命週期事件的實際管理和分發者。其中的方法

  • public void addObserver(LifecycleObserver observer)繼承自父類Lifecycle,添加生命週期監聽。
  • public void removeObserver( LifecycleObserver observer)繼承自父類Lifecycle,移除某個生命週期監聽。
  • public void handleLifecycleEvent(Lifecycle.Event event)通知監聽者最新的聲明週期,而且存儲。

3.3.1 通知更改 handleLifecycleEvent

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        State next = getStateAfter(event);
        moveToState(next);
    }
複製代碼

根據事件能獲取到組件進入的下一個狀態,而後將通知監聽改變狀態 :moveToState(next);MoveToState()方中,修改LifecycleRegistry中mState狀態,而後調用 sync()方法。

private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
            new FastSafeIterableMap<>();
複製代碼

LifecycleRegistry中有mObserverMap存儲這生命週期觀察者,FastSafeIterableMap是一個Map的數據結構,key爲LifecycleObserver,value爲ObserverWithState。

static class ObserverWithState {
     State mState;
     GenericLifecycleObserver mLifecycleObserver;

     ObserverWithState(LifecycleObserver observer, State initialState) {
         mLifecycleObserver = Lifecycling.getCallback(observer);
         mState = initialState;
     }

     void dispatchEvent(LifecycleOwner owner, Event event) {
         State newState = getStateAfter(event);
         mState = min(mState, newState);
         mLifecycleObserver.onStateChanged(owner, event);
         mState = newState;
     }
    }
複製代碼

Glide vs RXJava vs Jetpack

  • Glide做爲一個加載圖片的框架,當咱們使用Glide.with(View/Fragment/View)時獲取出具備感知組件生命週期的RequestManager並在相應的生命週期中開始/暫停/結束請求,結束是釋放相應資源。對組件生命週期的感知的核心原理向Request/Activity中放入一沒有界面的RequestManagerFragment,再相應的生命週期回調函數裏調用方法通知外界註冊了監聽函數的監聽者。
  • Jetpack中對生命週期的管理其核心思想和Glide相似,也是放入向組件中放入一個無界面的ReportFragment,這個ReportFragment就擁有和組件同步的生命週期,依此來向外界通知生命狀態,監聽者作相應的處理。兩個也是有不一樣,好比Glide關心onStart(),onStop()和onDestory()三個生命週期監聽而且在相應的生命週期回調函數中作了相應的處理,在onStart()中重試暫停或者失敗的請求,在onStop中取消正在進行的請求,在destory中釋放資源等。而Jetpack對 onCreate、onStart、onResume、onPause、onStop和onDestroy都作了監聽,這樣對監聽者提供更了更全面的狀態通知。
  • RxLifecycle中使用Compose和TakeUnitl操做符,告訴在指定的生命週期狀態下終止操做,相對於Glide和Jetpack中對生命週期的管理顯得單薄,並且若是要直接使用的話還要集成RxActivity或者RxFragment,固然也能夠本身實現用BehaviorSubject本身實現,但總的來講侵入性強。takeutil操做符帶來的問題就是當操做被終止後仍是會發送onComplete或者onError事件,這對於在這兩個方法中有業務處理的狀況來講不是一個優雅的實現。因而看到了知乎團隊基於無界面Fragment感知組件生命週期的思想,實現了一套RxLifecycle有興趣的能夠參考知乎RxLifecycle

留點念想

  • takeUntil()操做符是內部怎麼作到停止操做的?
  • Glide除了感知組件的生命週期是怎麼感知網絡變化並做出相應處理的?
  • 關於對Jetpack中對組件生命週期監聽的具體應用在LiveData和ViewModule中都有體現,他們是怎麼工做的?
  • 另外,Jetpack中LifecycleListener還能經過註解的方式回調執行怎麼作到的?
  • and so on

這些下回寫

相關文章
相關標籤/搜索