1. 程式人生 > >Android進階——藉助簡單便捷的ActivityLifecycleCallbacks實現全週期監聽Activity

Android進階——藉助簡單便捷的ActivityLifecycleCallbacks實現全週期監聽Activity

引言

在開發中由於業務的需求,我們需要在Activity對應的生命週期方法中去完成對應的工作,比如說需要在Activity的onResume中註冊某個SDK或者廣播接收器、抑或是嘗試開啟Camera、判斷app 是否在後臺執行除了令人蛋疼的判斷當前runningProcess 或者runningTasks 方法等,然後在Activity的onPause()中及時登出或釋放掉,以前也許會在每個Activity對應的方法中增加對應的程式碼即可,但是從一定意義上說這程式碼是冗餘的且不優雅,從Android4.0之後添加了Application.ActivityLifecycleCallbacks介面,我們開發者就有了一種更優雅的方案。

一、Application.ActivityLifecycleCallbacksgais概述

記得我第一次知道這個介面之後,第一時間跑到官網中查詢文件,結果發現Google 又偷懶了,Summary部分竟然一句話都沒有關於它的描述,差點懷疑是否進錯了網站,ORZ,才發現其實是這個介面太簡單了背後的原理也十分簡單,本來我還以為會是觀察者模式,後面發現就是一個普通回撥。但是藉助它我可以優雅地監控Activity的生命週期——一經註冊,就會自動監聽整個APP 中所有Activity 的生命週期方法的執行(會在對應的父類Activity的方法被執行之後自動觸發)

二、Application.ActivityLifecycleCallbacks原始碼急背後的原理簡要描述

Application.ActivityLifecycleCallbacks是Application中的一個介面,使用起來也很簡單,只需要呼叫registerActivityLifecycleCallbacks方法即可完成註冊(通常是在Application中完成的)。


public class Application extends ContextWrapper implements ComponentCallbacks2 {
    private ArrayList<ComponentCallbacks> mComponentCallbacks =
            new
ArrayList<ComponentCallbacks>(); private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks = new ArrayList<ActivityLifecycleCallbacks>(); private ArrayList<OnProvideAssistDataListener> mAssistCallbacks = null; /** @hide */ public LoadedApk mLoadedApk; public interface ActivityLifecycleCallbacks { void onActivityCreated(Activity activity, Bundle savedInstanceState); void onActivityStarted(Activity activity); void onActivityResumed(Activity activity); void onActivityPaused(Activity activity); void onActivityStopped(Activity activity); void onActivitySaveInstanceState(Activity activity, Bundle outState); void onActivityDestroyed(Activity activity); } public Application() { super(null); } @CallSuper public void onCreate() { } /** * This method is for use in emulated process environments. It will * never be called on a production Android device, where processes are * removed by simply killing them; no user code (including this callback) * is executed when doing so. */ @CallSuper public void onTerminate() { } @CallSuper public void onConfigurationChanged(Configuration newConfig) { Object[] callbacks = collectComponentCallbacks(); if (callbacks != null) { for (int i=0; i<callbacks.length; i++) { ((ComponentCallbacks)callbacks[i]).onConfigurationChanged(newConfig); } } } @CallSuper public void onLowMemory() { Object[] callbacks = collectComponentCallbacks(); if (callbacks != null) { for (int i=0; i<callbacks.length; i++) { ((ComponentCallbacks)callbacks[i]).onLowMemory(); } } } @CallSuper public void onTrimMemory(int level) { Object[] callbacks = collectComponentCallbacks(); if (callbacks != null) { for (int i=0; i<callbacks.length; i++) { Object c = callbacks[i]; if (c instanceof ComponentCallbacks2) { ((ComponentCallbacks2)c).onTrimMemory(level); } } } } /* **註冊ActivityLifecycleCallbacks回撥 */ public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) { synchronized (mActivityLifecycleCallbacks) { mActivityLifecycleCallbacks.add(callback); } } public void unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) { synchronized (mActivityLifecycleCallbacks) { mActivityLifecycleCallbacks.remove(callback); } } // ------------------ Internal API ------------------ /* package */ void dispatchActivityCreated(Activity activity, Bundle savedInstanceState) { Object[] callbacks = collectActivityLifecycleCallbacks(); if (callbacks != null) { for (int i=0; i<callbacks.length; i++) { ((ActivityLifecycleCallbacks)callbacks[i]).onActivityCreated(activity, savedInstanceState); } } } /* package */ void dispatchActivityStarted(Activity activity) { Object[] callbacks = collectActivityLifecycleCallbacks(); if (callbacks != null) { for (int i=0; i<callbacks.length; i++) { ((ActivityLifecycleCallbacks)callbacks[i]).onActivityStarted(activity); } } } /* package */ void dispatchActivityResumed(Activity activity) { Object[] callbacks = collectActivityLifecycleCallbacks(); if (callbacks != null) { for (int i=0; i<callbacks.length; i++) { ((ActivityLifecycleCallbacks)callbacks[i]).onActivityResumed(activity); } } } /* package */ void dispatchActivityPaused(Activity activity) { Object[] callbacks = collectActivityLifecycleCallbacks(); if (callbacks != null) { for (int i=0; i<callbacks.length; i++) { ((ActivityLifecycleCallbacks)callbacks[i]).onActivityPaused(activity); } } } /* package */ void dispatchActivityStopped(Activity activity) { Object[] callbacks = collectActivityLifecycleCallbacks(); if (callbacks != null) { for (int i=0; i<callbacks.length; i++) { ((ActivityLifecycleCallbacks)callbacks[i]).onActivityStopped(activity); } } } /* package */ void dispatchActivitySaveInstanceState(Activity activity, Bundle outState) { Object[] callbacks = collectActivityLifecycleCallbacks(); if (callbacks != null) { for (int i=0; i<callbacks.length; i++) { ((ActivityLifecycleCallbacks)callbacks[i]).onActivitySaveInstanceState(activity, outState); } } } /* package */ void dispatchActivityDestroyed(Activity activity) { Object[] callbacks = collectActivityLifecycleCallbacks(); if (callbacks != null) { for (int i=0; i<callbacks.length; i++) { ((ActivityLifecycleCallbacks)callbacks[i]).onActivityDestroyed(activity); } } } ... }

然後在Activity的對應的生命週期方法的內部,通過Application來呼叫對應的dispatchActivityXxxxx方法,從而實現全生命週期的監聽

public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2,Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback, WindowControllerCallback {
        ...
        @MainThread
    @CallSuper
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
        if (mLastNonConfigurationInstances != null) {
            mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);
        }
        if (mActivityInfo.parentActivityName != null) {
            if (mActionBar == null) {
                mEnableDefaultActionBarUp = true;
            } else {
                mActionBar.setDefaultDisplayHomeAsUpEnabled(true);
            }
        }
        if (savedInstanceState != null) {
            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
            mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
                    ? mLastNonConfigurationInstances.fragments : null);
        }
        mFragments.dispatchCreate();
        getApplication().dispatchActivityCreated(this, savedInstanceState);
        if (mVoiceInteractor != null) {
            mVoiceInteractor.attachActivity(this);
        }
        mCalled = true;
    }

    @CallSuper
    protected void onStart() {
        if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStart " + this);
        mCalled = true;

        mFragments.doLoaderStart();

        getApplication().dispatchActivityStarted(this);
    }
    ...
    }

三、ActivityLifecycleCallbacks的應用

Application.ActivityLifecycleCallbacks中對應的監聽的生命週期方法會在Activity中的生命方法呼叫父類的方法之後被觸發,由原始碼也可得知。

  • 繼承Application重寫onCreate等方法
  • 呼叫registerActivityLifecycleCallbacks方法註冊ActivityLifecycleCallbacks
package com.crazyview.activitylifecycle;

import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import android.util.Log;

/**
 * Created by cmo on 2017/12/23.
 */

public class LifecycleApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        init();
    }

    private void init() {
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                Log.e("Lifecycle",activity.getLocalClassName()+" was Created"+"activity==null   "
                        +(activity==null)+"     activity.isFinishing()  "+(activity.isFinishing())+"    activity.isDestroyed()  "+activity.isDestroyed());
            }

            @Override
            public void onActivityStarted(Activity activity) {
                Log.e("Lifecycle",activity.getLocalClassName()+" was Started"+"activity==null   "
                            +(activity==null)+"     activity.isFinishing()   "+(activity.isFinishing())+"   activity.isDestroyed()  "+activity.isDestroyed());
            }

            @Override
            public void onActivityResumed(Activity activity) {
                 Log.e("Lifecycle",activity.getLocalClassName()+" was oResumed"+"activity==null   "
                        +(activity==null)+"activity.isFinishing()   "+(activity.isFinishing())+"activity.isDestroyed() "+activity.isDestroyed());
            }

            @Override
            public void onActivityPaused(Activity activity) {
                Log.e("Lifecycle",activity.getLocalClassName()+" was Pauseed"+"activity==null   "
                        +(activity==null)+"activity.isFinishing()   "+(activity.isFinishing())+"activity.isDestroyed()  "+activity.isDestroyed());
            }

            @Override
            public void onActivityStopped(Activity activity) {
                Log.e("Lifecycle",activity.getLocalClassName()+" was Stoped"+"activity==null    "
                        +(activity==null)+"activity.isFinishing()   "+(activity.isFinishing())+"activity.isDestroyed() "+activity.isDestroyed());
            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
                Log.e("Lifecycle",activity.getLocalClassName()+" was SaveInstanceState"+"activity==null "
                        +(activity==null)+"activity.isFinishing()   "+(activity.isFinishing())+"activity.isDestroyed()  "+activity.isDestroyed());
            }

            @Override
            public void onActivityDestroyed(Activity activity) {
                Log.e("Lifecycle",activity.getLocalClassName()+" was Destroyed"+"activity==null"
                        +(activity==null)+"  activity.isFinishing()  "+(activity.isFinishing())+"  activity.isDestroyed()"+activity.isDestroyed());
            }
        });
    }
}
  • 在清單中宣告Application,無需在Activity新增額外的程式碼就可以實現監控
package com.crazyview.activitylifecycle;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    public static final String LIFECYCLE = "MainActivity:Lifecycle";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.e(LIFECYCLE, "onCreate() is Running__before super.onCreate called");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e(LIFECYCLE, "onCreate() is Running__after super.onCreate called");
    }

    @Override
    protected void onRestart() {
        Log.e(LIFECYCLE, "onRestart() is Running__before super's called");
        super.onRestart();
        Log.e(LIFECYCLE, "onRestart() is Running__after super's called");
    }

    @Override
    protected void onStart() {
        Log.e(LIFECYCLE, "onStart() is Running__before super.onStart called");
        super.onStart();
        Log.e(LIFECYCLE, "onStart() is Running__after super.onStart called");
    }

    @Override
    protected void onResume() {
        Log.e(LIFECYCLE, "onResume() is Running__before super.onResume called");
        super.onResume();
        Log.e(LIFECYCLE, "onResume() is Running__after super.onResume called");
    }

    @Override
    protected void onPause() {
        Log.e(LIFECYCLE, "onPause() is Running__before super's called");
        super.onPause();
        Log.e(LIFECYCLE, "onPause() is Running__after super's called");
    }

    @Override
    protected void onStop() {
        Log.e(LIFECYCLE, "onStop() is Running__before super's called");
        super.onStop();
        Log.e(LIFECYCLE, "onStop() is Running__after super's called");
    }

    @Override
    protected void onDestroy() {
        Log.e(LIFECYCLE, "onDestroy() is Running__before super's called");
        super.onDestroy();
        Log.e(LIFECYCLE, "onDestroy() is Running__after super's called");
    }

    public void toTask(View view) {
        startActivity(new Intent(this, TaskActivity.class));
        //finish();
    }
}

開啟MainActivity時候的執行結果:
這裡寫圖片描述
finish當前Activity時:
這裡寫圖片描述

PS:一些有用的adb命令

1、通過adb 命令獲取當前執行的Activity

adb shell dumpsys activity | findstr "mFocusedActivity"

2、通過adb 使用命令列擷取對應的log並儲存到硬碟對應目錄下

adb logcat -s tag >d:log.txt

3、將log和當前時間 儲存到當前目錄下

adb logcat -v time >a.log

4、通過android.app.ActivityManager獲取topActivity

 public static String getTopActivity(Context context) {
        android.app.ActivityManager am = (android.app.ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
        ComponentName cn = am.getRunningTasks(1).get(0).topActivity;
        return cn.getShortClassName().toString();
    }