如何綁定頁面生命週期(二)-基於Android Architecture Components的Lifecycle實現

上篇文章如何綁定頁面生命週期(一)-Glide實現介紹了Glide實現生命週期感知的原理,這裏咱們再介紹基於Android Architecture Components的Lifecycle實現頁面生命週期感知。android

Lifecycle是Android Architecture Components(以後簡稱AAC)的一個組件,用於將系統組件(Activity、Fragment等等)的生命週期分離到Lifecycle類,Lifecycle容許其餘類做爲觀察者,觀察組件生命週期的變化。git

基於AAC實現組件生命週期觀察實踐

  • 控件實現LifecycleObserver接口,內部經過@OnLifecycleEvent註解聲明生命週期事件
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,好比在實現了LifecycleRegistryOwner接口的Activity中。定義LifecycleRegistry實例,並將控件lifecycleRegistry實例中的監聽集合中。
public class MainActivity extends AppCompatActivity implements LifecycleRegistryOwner {
	// 定義LifecycleRegistry實例
    private LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 加入監聽集合
        getLifecycle().addObserver(new LifecycleObserverDemo());        
    }

    @Override
    public LifecycleRegistry getLifecycle() {
        return lifecycleRegistry;
    }
}
複製代碼

只須要如上兩步,當Activity頁面生命週期發生變化時,都會通知到LifecycleObserverDemo。一樣,本文以Activity爲例,介紹Lifecycle感知生命週期的原理。github

生命週期綁定實現原理

實現原理簡介

經過在對指定activity註冊無UI的Fragment,傳遞頁面Activity生命週期到Fragment。而後經過Fragment綁定LifecycleRegistry,當Fragment的生命週期變化時,回調LifecycleRegistry中LifecycleObserver對象相應的生命週期回調方法。bash

如何傳遞生命週期

下圖是文章Android Architecture Component -- Lifecycle 淺析中關於Lifecycle生命週期傳遞的一幅圖,我以爲很清晰地展現了生命週期的傳遞過程。下面咱們跟着這幅圖,來一步步看一下生命週期是如何傳遞的。app

生命週期傳遞到LifecycleObserver

  • 如何在Activity上註冊無UI的ReportFragment框架

    首先看下LifecycleDispatcher初始化的過程:ide

    • 利用 ContentProvider 的特色在應用程序初始化時,向其注入兩行代碼:
    LifecycleDispatcher.init(getContext());
    ProcessLifecycleOwner.init(getContext());  // 監聽整個應用先後臺切換
    複製代碼
    • 這個ContentProvider從哪裏來?查看apk中的AndroidManifest.xml文件,發現多了一個ContentProvider聲明:
    <provider
        android:name="android.arch.lifecycle.LifecycleRuntimeTrojanProvider"
        android:authorities="${applicationId}.lifecycle-trojan"
        android:exported="false"
        android:multiprocess="true" />
    複製代碼

在這個LifecycleRuntimeTrojanProvider(低版本的AAC裏,這個類叫ProcessLifecycleOwnerInitializer)的初始化方法中,實現了LifecycleDispatcher的相應初始化操做。函數

下面再來看一下LifecycleDispatcher的init方法:post

static void init(Context context) {
    if (sInitialized.getAndSet(true)) {
        return;
    }
    ((Application) context.getApplicationContext())
            .registerActivityLifecycleCallbacks(new DispatcherActivityCallback());
}
複製代碼

在 LifecycleDispatcher#init(Context) 中,它經過 registerActivityLifecycleCallbacks 方法,向當前的 Application 註冊一個 DispatcherActivityCallback。但 Lifecycle 並沒使用 ActivityLifecycleCallbacks 來監聽並派發生命週期事件。而是經過一個無 UI 的 Fragment,在 DispatcherActivityCallback#onActivityCreated 能夠看到它在 Activity#onCreate 時,爲 Activity 添加一個 ReportFragment。最終由 ReportFragment 來監聽各個生命週期事件,而後傳遞給 LifecycleRegistry。ui

  • 無UI的Fragment與LifecycleRegistry創建聯繫

查看ReportFragment的生命週期回調方法:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    dispatchCreate(mProcessListener);
    dispatch(Lifecycle.Event.ON_CREATE);
}

@Override
public void onStart() {
    super.onStart();
    dispatchStart(mProcessListener);
    dispatch(Lifecycle.Event.ON_START);
}

@Override
public void onResume() {
    super.onResume();
    dispatchResume(mProcessListener);
    dispatch(Lifecycle.Event.ON_RESUME);
}

@Override
public void onPause() {
    super.onPause();
    dispatch(Lifecycle.Event.ON_PAUSE);
}

@Override
public void onStop() {
    super.onStop();
    dispatch(Lifecycle.Event.ON_STOP);
}

@Override
public void onDestroy() {
    super.onDestroy();
    dispatch(Lifecycle.Event.ON_DESTROY);
    // just want to be sure that we won't leak reference to an activity mProcessListener = null; } 複製代碼

回調生命週期方法時,會調用dispatch(Lifecycle.Event event)方法。看下dispatch(Lifecycle.Event event)方法的源碼:

private void dispatch(Lifecycle.Event event) {
    Activity activity = getActivity();
    if (activity instanceof LifecycleRegistryOwner) {
        ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
        return;
    }

    if (activity instanceof LifecycleOwner) {
        Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
        if (lifecycle instanceof LifecycleRegistry) {
            ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
        }
    }
}
複製代碼

這裏會經過ReportFragment註冊的Activity的getLifecycle()方法獲取LifecycleRegistry,而後調用LifecycleRegistry的handleLifecycleEvent(@NonNull Lifecycle.Event event)處理傳遞的生命週期Event。

  • _LifecycleAdapter如何與LifecycleRegistry創建聯繫

    在LifecycleRegistry中,定義了以下的map:

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

    當咱們在頁面Activity中將觀察者加入集合時,加入的就是上面定義的mObserverMap。ObserverWithState對象構造函數初始化時,經過Lifecycling.getCallback(observer)方法返回GenericLifecycleObserver對象,實際上就是_LifecycleAdapter對象。由於_LifecycleAdapter實現了GenericLifecycleObserver。

    static GenericLifecycleObserver getCallback(Object object) {
        if (object instanceof FullLifecycleObserver) {
            return new FullLifecycleObserverAdapter((FullLifecycleObserver) object);
        }
    
        if (object instanceof GenericLifecycleObserver) {
            return (GenericLifecycleObserver) object;
        }
    
        final Class<?> klass = object.getClass();
        int type = getObserverConstructorType(klass);
        if (type == GENERATED_CALLBACK) {
            List<Constructor<? extends GeneratedAdapter>> constructors =
                    sClassToAdapters.get(klass);
            if (constructors.size() == 1) {
                GeneratedAdapter generatedAdapter = createGeneratedAdapter(
                        constructors.get(0), object);
                return new SingleGeneratedAdapterObserver(generatedAdapter);
            }
            GeneratedAdapter[] adapters = new GeneratedAdapter[constructors.size()];
            for (int i = 0; i < constructors.size(); i++) {
                adapters[i] = createGeneratedAdapter(constructors.get(i), object);
            }
            return new CompositeGeneratedAdaptersObserver(adapters);
        }
        return new ReflectiveGenericLifecycleObserver(object);
    }
    複製代碼

基於註解生成了_LifecycleAdapter 的class,經過反射生成_LifecycleAdapter對象

  • _LifecycleAdapter回調生命週期方法,繼續傳遞生命週期給最終的觀察者

LifecycleRegistry和_LifecycleAdapter創建聯繫後,生命週期會經過調用ObserverWithState的dispatchEvent方法:

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

最終,會調用mLifecycleObserver,即咱們前面返回的_LifecycleAdapter的onStateChanged方法。下面看下_LifecycleAdapter的實現:

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;
  }
}
複製代碼

上面的類,能夠在 build 目錄下找到。這是註解處理器爲咱們生成了 LifecycleObserverDemo_LifecycleAdapter,不過這只是一個適配器,用於將生命週期事件派發到 LifecycleObserverDemo 對應的方法。至此,LifecycleObserverDemo實現了對頁面Activity生命週期的感知。

核心類介紹

  • LifecycleObserver:接口,標記一個類是可觀察的,基於註解實現相應回調方法
  • Lifecycle:抽象類,擁有android生命週期
  • LifecycleRegistry:繼承Lifecycle,能夠處理多LifecycleObserver
  • LifecycleOwner:接口,持有一個android lifecycle
  • LifecycleRegistryOwner:接口,繼承LifecycleOwner,返回LifecycleRegistry
  • LifecycleDispatcher:在Application中hook,觀察activity的生命週期並分發
  • LifecycleRuntimeTrojanProvider:LifecycleDispatcher等初始化

生命週期管理框架實踐

Demo省略了註解相關步驟,須要觀察者本身去實現一個ZRLifecycleObserver接口。雖然稍有不一樣,可是不妨礙理解。

Demo的框架圖以下所示:

框架圖

使用的話也比較簡單,主要進行如下一些設置。

  • 觀察者實現ZRLifecycleObserver接口
public class MyView extends View implements ZRLifecycleObserver {

    public MyView(Context context) {
        this(context, null);
    }

    public MyView(Context context,
            @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void onCreate() {
        System.out.println("MyView onCreate");
    }

    @Override
    public void onStart() {
        System.out.println("MyView onStart");
    }

    @Override
    public void onResume() {
        System.out.println("MyView onResume");
    }

    @Override
    public void onPause() {
        System.out.println("MyView onPause");
    }

    @Override
    public void onStop() {
        System.out.println("MyView onStop");
    }

    @Override
    public void onDestroy() {
        System.out.println("MyView onDestroy");
    }

    @Override
    public void onRestart() {
        System.out.println("MyView onRestart");
    }
}
複製代碼
  • 應用啓動時初始化ZRLifecycleDispatcher
public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        ZRLifecycleDispatcher.init(this);
    }
}
複製代碼
  • 被觀察頁面實現ZRLifecycleRegistryOwner,並將要要觀察此頁面生命週期的觀察者對象加入集合
public class MainActivity extends Activity implements ZRLifecycleRegistryOwner {

    private ZRLifecycleRegistry lifecycleRegistry = new ZRLifecycleRegistry(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MyView myView = findViewById(R.id.view_test);

        getLifecycle().addObserver(myView);

    }

    @Override
    public ZRLifecycleRegistry getLifecycle() {
        return lifecycleRegistry;
    }
}
複製代碼

具體工程代碼能夠從這裏獲取:CustomAACLifecycleDemo

結束

至此,關於AAC如何綁定頁面生命週期的原理講解結束。在上一篇文章如何綁定頁面生命週期(一)-Glide實現,介紹了Glide綁定生命週期的原理。兩種綁定頁面生命週期的方式,你們能夠對比着看,相信確定會對綁定頁面生命週期有更加深刻的瞭解。

參考

Android Architecture Component -- Lifecycle 淺析

相關文章
相關標籤/搜索