Activity生命周期监听ActivityLifecycleCallbacks

QuibblerQuibbler 2020-11-22 约 22 分钟 3477 次阅读

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监听前后台状态

        

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w