Activity生命周期监听ActivityLifecycleCallbacks
一个应用有很多Activity,一些重复的代码,可以通过抽象出BaseActivity类抽取出来。也可以通过hock的方式启动应用增加额外判断。

Activity的生命周期如何统一管理呢?曾经接触过UMeng的埋点SDK,不需要任何配置,即可监听应用的所有页面活动并上报埋点。他们是通过什么来实现的呢?答案就是:ActivityLifecycleCallbacks。它的源码不难看懂,详见ActivityLifecycleCallbacks的原理分析。
1、ActivityLifecycleCallbacks
从Android API 14开始(Android 4.0),在Application类中新增了ActivityLifecycleCallbacks接口,方便应用统一管理监控全部Activity的生命周期。
ActivityLifecycleCallbacks activityLifecycleCallbacks = new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(@NonNull Activity activity) {
}
@Override
public void onActivityResumed(@NonNull Activity activity) {
}
@Override
public void onActivityPaused(@NonNull Activity activity) {
}
@Override
public void onActivityStopped(@NonNull Activity activity) {
}
@Override
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
}
@Override
public void onActivityDestroyed(@NonNull Activity activity) {
}
};有这么灵活的接口,程序员就可以发挥创造力,完成很多功能:
①应用程序锁,每次程序退出后台,重新进入应用,都需要输入解锁密码。放在ActivityLifecycleCallbacks轻松实现,hock也是一种方式。
②判断应用在前台还是后台
③使用Stack栈数据结构保存Activity,限制Activity的数量
④限制某个Activity只有一个实例,finish()之前的(也可用SingleInstance启动模式)
2、接口
现在看的源码以及官方文档,ActivityLifecycleCallbacks中的接口比目前各大博客中提及到的多,Android在后面又增加了很多生命周期相关的回调监听接口。
2.1、最初7个接口
下面这7个方法是ActivityLifecycleCallbacks接口中,必须要要实现的。
①onActivityCreated(Activity activity,Bundle savedInstanceState)
②onActivityStarted(Activity activity)
③onActivityResumed(Activity activity)
④onActivityPaused(Activity activity)
⑤onActivityStopped(Activity activity)
⑥onActivitySaveInstanceState(Activity activity, Bundle outState)
⑦onActivityDestroyed(Activity activity)
2.2、新增7对默认接口
从最新的源码来看,分别对上面的7种生命周期回调新增了前(Pre)、后(Post)各两个回调。为了兼容老代码,这些新增的回调方法在接口中都是default的空方法。即使旧项目没有实现这些新增的方法也不要紧,不影响运行,可见框架在兼容这方面做得很不错。
①default void onActivityPreCreated( Activity activity, Bundle savedInstanceState)
②default void onActivityPostCreated( Activity activity, Bundle savedInstanceState)
③default void onActivityPreStarted( Activity activity)
④default void onActivityPostStarted( Activity activity)
⑤default void onActivityPreResumed( Activity activity)
⑥default void onActivityPostResumed( Activity activity)
⑦default void onActivityPrePaused( Activity activity)
⑧default void onActivityPostPaused( Activity activity)
⑨default void onActivityPreStopped( Activity activity)
⑩default void onActivityPostStopped( Activity activity)
⑪default void onActivityPreSaveInstanceState( Activity activity,Bundle outState)
⑫default void onActivityPostSaveInstanceState( Activity activity,Bundle outState)
⑬default void onActivityPreDestroyed( Activity activity)
⑭default void onActivityPostDestroyed( Activity activity)
3、注册ActivityLifecycleCallbacks
ActivityLifecycleCallbacks回调的注册与反注册。
3.1、注册ActivityLifecycleCallbacks
构造好实现ActivityLifecycleCallbacks接口的实例,即可将其注册给Application。调用Application的registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback)方法
该方法的实现如下:
public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
synchronized (mActivityLifecycleCallbacks) {
mActivityLifecycleCallbacks.add(callback);
}
}在Application类中定义了若干中不同callback的集合,每注册一个都会被加入到集合中。ActivityLifecycleCallbacks实例会加入到mActivityLifecycleCallbacks集合中。
public class Application extends ContextWrapper implements ComponentCallbacks2 {
private static final String TAG = "Application";
@UnsupportedAppUsage
ArrayList<ComponentCallbacks> mComponentCallbacks = new ArrayList<ComponentCallbacks>();
@UnsupportedAppUsage
ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks = new ArrayList<ActivityLifecycleCallbacks>();
@UnsupportedAppUsage
ArrayList<OnProvideAssistDataListener> mAssistCallbacks = null;
...
}3.2、解注册ActivityLifecycleCallbacks
Android开发中很多注册操作都有对应的反注册操作,类似这样的成对操作有很多。实现原理也和上面的类似就是把注册的对象实例添加到集合中,反注册的时候再移出去。所以不进行反注册很容易造成内存泄漏。
反注册ActivityLifecycleCallbacks调用Application中的unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback)方法。
public void unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
synchronized (mActivityLifecycleCallbacks) {
mActivityLifecycleCallbacks.remove(callback);
}
}一般可以在Application中的onTerminate()结束应用回调中反注册,虽然该方法不一定保证被调用。
@Override
public void onTerminate() {
super.onTerminate();
unregisterActivityLifecycleCallbacks(activityLifecycleCallbacks);
}3.3、Activity中注册
在API 29中,Activity也新增了ActivityLifecycleCallbacks的注册和反注册接口,也可以使用上面的方法进行注册和反注册。
4、示例
ActivityLifecycleCallbacks有什么用处呢?举个例子。
4.1、判断应用前后台
在onActivityStarted()和onActivityStopped()回调中,对可见的Activity计数。
private int mActivateActivityCount = 0;
ActivityLifecycleCallbacks activityLifecycleCallbacks = new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {}
@Override
public void onActivityStarted(@NonNull Activity activity) {
if (mActivateActivityCount == 0) { //可见应用从0开始,意味着应用进入前台
Log.d(TAG, "onActivityResumed 进入前台");
}
mActivateActivityCount++;
}
@Override
public void onActivityResumed(@NonNull Activity activity) {}
@Override
public void onActivityPaused(@NonNull Activity activity) {}
@Override
public void onActivityStopped(@NonNull Activity activity) {
mActivateActivityCount--;
if (mActivateActivityCount == 0) {//可见应用变为0,意味着应用进入后台
Log.d(TAG, "onActivityStopped 进入后台");
}
}
@Override
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {}
@Override
public void onActivityDestroyed(@NonNull Activity activity) {}
};4.2、Activity数量统计
每当Activity Created的时候将其入栈,数量加一。每当Activity生命周期回调Destroy的时候将其移除栈中,同时计数减一。
private Stack<Activity> mActivities = new Stack<>();
private int mActivityCount = 0;
ActivityLifecycleCallbacks activityLifecycleCallbacks = new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
mActivities.push(activity);
mActivityCount++;
Log.d(TAG, "onActivityCreated " + mActivityCount);
}
@Override
public void onActivityStarted(@NonNull Activity activity) {}
@Override
public void onActivityResumed(@NonNull Activity activity) {}
@Override
public void onActivityPaused(@NonNull Activity activity) {}
@Override
public void onActivityStopped(@NonNull Activity activity) {}
@Override
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {}
@Override
public void onActivityDestroyed(@NonNull Activity activity) {
mActivities.remove(activity);
mActivityCount--;
Log.d(TAG, "onActivityDestroyed " + mActivityCount);
}
};4.3、Activity回到前台统一动作
使用一些应用的时候常常会发现当应用进入后台,在切换回前台时,会显示几秒的广告。这是如何统一做到的呢?利用ActivityLifecycleCallbacks可以方便的统一实现。

结合前面判断应用前后台的方式,只需要再增加一些代码即可,比如在onActivityStarted(Activity activity)判断当应用从后台进入前台时,启动广告页面。
@Override
public void onActivityStarted(@NonNull Activity activity) {
if (mActivateActivityCount == 0) { //可见应用从0开始,意味着应用进入前台
Log.d(TAG, "onActivityResumed 进入前台");
if (activity instanceof MainActivity) {
Intent intent = new Intent(activity, AdsActivity.class);
activity.startActivity(intent);
}
}
mActivateActivityCount++;
}对于加密应用这是一个不错的思路,启动Activity前判断特定条件,不符合就启动登录或者输入密码的Activity页面。
参考资料:
Reference > ActivityLifecycleCallbacks">Android Developers > Reference > ActivityLifecycleCallbacks
Android使用ActivityLifecycleCallbacks管理Activity和区分App前后台
优雅的使用ActivityLifecycleCallbacks管理Activity和区分App前后台
ActivityLifecycleCallbacks管理Activity栈(监听home键)
ActivityLifecycleCallbacks监听前后台状态

