• Application


    一、概念理解

    Base class for maintaining global application state. You can provide your own implementation by creating a subclass and specifying the fully-qualified name of this subclass as the "android:name" attribute in your AndroidManifest.xml's <application> tag. The Application class, or your subclass of the Application class, is instantiated before any other class when the process for your application/package is created.

    Note: There is normally no need to subclass Application. In most situations, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), include Context.getApplicationContext() as a Context argument when invoking your singleton's getInstance() method.

    Application是维持全局应用状态的基类,单例模式,且先于其他任意组件被创建。Application组件被设计的初衷是对整体应用级别管理负责,对其正确使用应该避免两个极端

    1. 过度使用——将Application当做单例工具类,耦合太多非应用级别的工具方法或业务逻辑,造成Application类臃肿
    2. 从不使用——因不熟悉而不敢使用或忘记使用,不使用没有错,但有时适当使用会减少代码重复,提升性能,且其自身扩展方法也会为某些特殊业务提供思路

    Application实际上继承自Context,继承来的方法不必多说,也不是重点。既然有必要子类化,那它也必然会扩展自己的方法来实现其特有功能,也就是和应用管理相关方法。下面将重点介绍这些方法。


    二、Application实战应用

    Application的应用管理相关功能可以从其维护的三个List来分析:

        private ArrayList<ComponentCallbacks> mComponentCallbacks = new ArrayList<ComponentCallbacks>();//系统配置变更、内存管理
        private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks = new ArrayList<ActivityLifecycleCallbacks>();//Activity生命周期管理
        private ArrayList<OnProvideAssistDataListener> mAssistCallbacks = null; //协助数据

    (1)ComponentCallbacks/ComponentCallbacks2

    用于系统配置变化、内存紧张时获得回调。该接口并非只有Application实现,Activity和Service等其他组件都有实现。而且还可以自定义实现接口,通过API注册。

        void onConfigurationChanged(Configuration newConfig);//系统状态配置如横竖屏、语言等变化时回调
        void onLowMemory();//后台进程被杀后回调
        void onTrimMemory(@TrimMemoryLevel int level);//根据不同内存状态来回调

    其中onLowMemory和onTrimMemory的区别:

    1. OnLowMemory被回调时,已经没有后台进程;而onTrimMemory被回调时,还有后台进程。
    2. OnLowMemory是在最后一个后台进程被杀时调用,一般情况是low memory killer 杀进程后触发;OnTrimMemory的触发更频繁,每次计算进程优先级时,只要满足条件,都会触发。
    3. 通过一键清理后,OnLowMemory不会被触发,而OnTrimMemory会被触发一次。

    (2)ActivityLifecycleCallbacks

    该接口用于对应用所有Activity的生命周期做集中回调管理,是Application独有扩展功能。注册该接口后每个Activity的生命周期发生变化后都会获得回调,可以很方便的做记录和管理。

            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);
            }

    实现原理也比较简单,以onActivityCreated为例, 在Application中有如下方法两个方法

        //注册回调
        public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback)
        //分发回调
        /* package */ void dispatchActivityCreated(Activity activity, Bundle savedInstanceState)

    通过registerActivityLifecycleCallbacks方法注册回调,查看Activity源码,当onCreate时,再通过dispatchActivityCreated方法分发给各回调。

        protected void onCreate(@Nullable Bundle savedInstanceState) {
            ...
            getApplication().dispatchActivityCreated(this, savedInstanceState);
            ...
        }

    在实际应用中,通过注册registerActivityLifecycleCallbacks回调,可以对Activity的状态和数量做更精准的监控。

    应用一:限制Activity实例数量

    比如,我们要限制ActivityDetail页面的数量不超过MAX_ACTIVITY_DETAIL_NUM,可以在onActivityCreated回调方法中做如下处理(这是Activity启动模式无法做到的)

        public static Stack<ActivityDetail> store;   
        @Override 
        public void onActivityCreated(Activity activity, Bundle bundle) {
            if (activity instanceof ActivityDetail) {
                if (store.size() >= MAX_ACTIVITY_DETAIL_NUM) {
                    store.peek().finish(); //移除栈底并finish,保证不超过指定数量 
                }
                tore.add((ActivityDetail) activity);
            }
        }

    应用二:控制相同内容的Activity只有一个实例

    比如,要展示商品A的ActivityDetail实例已经存在,就没必要再创建一个展示相同内容的ActivityDetail。

    系统级应用可以调用如下方法(需要Android.permission.STOP_APP_SWITCHES权限)

        for(ActivityDetail activityDetail : store){ 
            if(id.equalsIgnoreCase(activityDetail.getID())){ //当前商品id相同证明已有相同页面
                 ActivityManager am = (ActivityManager) getAppContext().getSystemService(Activity.ACTIVITY_SERVICE); 
                 am.moveTaskToFront(activityDetail.getTaskId(), ActivityManager.MOVE_TASK_NO_USER_ACTION); 
                 return true;
            }
        }

    非系统级应用只能finish掉已经存在的页面,重新打开一个新的页面

        for(ActivityDetail activityDetail : store){ 
            if(id.equalsIgnoreCase(activityDetail.getID())){ //当前商品id相同证明已有相同页面
                 activityDetail.finish();
                 return true;
            }
        }

    应用三:判断App前后台状态

    每当一个Activity切到前台时都会执行onStart,切到后台时都会执行onStop,所以只需要在onActivityStarted和onActivityStopped回调中做一个简单的计数器即可

              mActivityCount = 0;        
              registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
                                ... 
                    @Override
                    public void onActivityStarted(Activity activity) {
                        Log.d(TAG,"onActivityStarted");
                        mActivityCount++;
                    }
         
                    @Override
                    public void onActivityStopped(Activity activity) {
                        Log.d(TAG,"onActivityStopped");
                        mActivityCount--;
                    }
                                ...
                });

    当mActivityCount == 0时App为后台,否则即是前台。

  • 相关阅读:
    服务器/服务器架构/阿里云服务器/虚拟机
    第十五章、线程之协程
    第十五章、线程池和进程池
    第十五章、线程之queue模块的各种队列
    第十五章、Python多线程之信号量和GIL
    第十五章、Python多线程同步锁,死锁和递归锁
    第十五章、并发编程之守护线程
    第十五章、并发编程之线程
    抢票小程序
    队列与生产者消费者模型
  • 原文地址:https://www.cnblogs.com/not2/p/10845320.html
Copyright © 2020-2023  润新知