上篇文章如何繫結頁面生命週期(一)-Glide實現介紹了Glide實現生命週期感知的原理,這裡我們再介紹基於Android Architecture Components的Lifecycle實現頁面生命週期感知。
Lifecycle是Android Architecture Components(之後簡稱AAC)的一個元件,用於將系統元件(Activity、Fragment等等)的生命週期分離到Lifecycle類,Lifecycle允許其他類作為觀察者,觀察元件生命週期的變化。
基於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感知生命週期的原理。
生命週期繫結實現原理
實現原理簡介
通過在對指定activity註冊無UI的Fragment,傳遞頁面Activity生命週期到Fragment。然後通過Fragment繫結LifecycleRegistry,當Fragment的生命週期變化時,回撥LifecycleRegistry中LifecycleObserver物件相應的生命週期回撥方法。
如何傳遞生命週期
下圖是文章Android Architecture Component -- Lifecycle 淺析中關於Lifecycle生命週期傳遞的一幅圖,我覺得很清晰地展示了生命週期的傳遞過程。下面我們跟著這幅圖,來一步步看一下生命週期是如何傳遞的。
-
如何在Activity上註冊無UI的ReportFragment
首先看下LifecycleDispatcher初始化的過程:
- 利用 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方法:
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的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繫結生命週期的原理。兩種繫結頁面生命週期的方式,大家可以對比著看,相信肯定會對繫結頁面生命週期有更加深入的瞭解。