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组件被设计的初衷是对整体应用级别管理负责,对其正确使用应该避免两个极端
- 过度使用——将application当做单例工具类,耦合太多非应用级别的工具方法或业务逻辑,造成application类臃肿
- 从不使用——因不熟悉而不敢使用或忘记使用,不使用没有错,但有时适当使用会减少代码重复,提升性能,且其自身扩展方法也会为某些特殊业务提供思路
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的区别:
- onlowmemory被回调时,已经没有后台进程;而ontrimmemory被回调时,还有后台进程。
- onlowmemory是在最后一个后台进程被杀时调用,一般情况是low memory killer 杀进程后触发;ontrimmemory的触发更频繁,每次计算进程优先级时,只要满足条件,都会触发。
- 通过一键清理后,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为后台,否则即是前台。
推荐阅读
-
发布WEB站点时出现Server Application Unavailable
-
spring boot application properties配置实例代码详解
-
javascript asp教程第十一课--Application 对象
-
IIS 错误 Server Application Error 详细解决方法
-
Android application捕获崩溃异常怎么办
-
SpringBoot -- 事件(Application Event)
-
C# MVC 全局错误Application_Error中处理(包括Ajax请求)
-
微软发布的Data Access Application Block的使用代码
-
SpringBoot Application注解原理及代码详解
-
Application Cache未缓存文件无法访问无法加载问题