上篇文章如何綁定頁面生命週期(一)-Glide實現介紹了Glide實現生命週期感知的原理,這裏咱們再介紹基於Android Architecture Components的Lifecycle實現頁面生命週期感知。android
Lifecycle是Android Architecture Components(以後簡稱AAC)的一個組件,用於將系統組件(Activity、Fragment等等)的生命週期分離到Lifecycle類,Lifecycle容許其餘類做爲觀察者,觀察組件生命週期的變化。git
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");
}
}
複製代碼
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
如何在Activity上註冊無UI的ReportFragment框架
首先看下LifecycleDispatcher初始化的過程:ide
LifecycleDispatcher.init(getContext());
ProcessLifecycleOwner.init(getContext()); // 監聽整個應用先後臺切換
複製代碼
<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
查看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
對象
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生命週期的感知。
Demo省略了註解相關步驟,須要觀察者本身去實現一個ZRLifecycleObserver接口。雖然稍有不一樣,可是不妨礙理解。
Demo的框架圖以下所示:
使用的話也比較簡單,主要進行如下一些設置。
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");
}
}
複製代碼
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
ZRLifecycleDispatcher.init(this);
}
}
複製代碼
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綁定生命週期的原理。兩種綁定頁面生命週期的方式,你們能夠對比着看,相信確定會對綁定頁面生命週期有更加深刻的瞭解。