Preface
在学习一个SDK的时候,遇到了Application
类的相关知识,其实之前也有学习过Application
类的一些知识,但是日常开发中使用频率不高,忘得差不多了.现在重新来总结下Application
的使用
英语基础好的可以去参考官方文档
下面是官网对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.
大概意思就是Application是用来维护全局应用状态的基类.可以通过自己创建子类并且在Manifest.xml
文件中通过name
属性来标记,用来实现自定义的功能.Application类将会在任何类之前实例化
继承关系
Application
类继承自ContextWarpper
类
下面是示意图
特点
-
单例模式:每个App都有且只有一个Application的实例对象(多进程APP除外),可以通过继承Application子类来进行自定义,如果没有自定义的话,APP会在打开是自动创建一个默认的实例对象.
-
生命周期:APP开启时就会开始实例化Application对象,Application实例的生命周期是最长的,拥有和APP一样长的生命周期
-
获取方式:如果没有自定义Application的话,同样可以获取到Application对象,使用
Activity.getApplication()
或者Context.getApplicationContext()
方法都可以获取到对象.
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) //这两种方法都可以获取到实例对象 val application = application val otherApplication = applicationContext}复制代码
- 全局实例:在不同的组件中(如:Activity,Service),都可以获取Application对象,并且都会是同一个对象
方法介绍
onCreate()
-
调用时间:
当应用打开时,创建应用程序时调用此方法.
Tip:这不是Activity的onCreate(),默认是空实现.
-
使用方式:
可以用来初始化数据一些全局变量,对象,也可以用来做一些环境的配置.
-
演示:
class MyApplication: Application() { var whatever = "Whatever" override fun onCreate() { super.onCreate() whatever = "Hello" //Do something... }}复制代码
注册ComponentCallback2
-
简单说明:
上面的示意图中其实还显示了,Application类是实现了ComponentCallback2接口的,这个接口里面有三个可以覆写的方法,可以通过
registerComponentCallbacks()
方法来进行注册,也可以使用unregisterComponentCallbacks()
来注销. -
使用:
override fun onCreate() { super.onCreate() registerComponentCallbacks(object : ComponentCallbacks2 { override fun onLowMemory() { } override fun onConfigurationChanged(newConfig: Configuration?) { } override fun onTrimMemory(level: Int) { } }) }复制代码
onLowMemory()
这是上面ComponentCallback2
接口中的方法,用于在Android4.0之前的内存检测,开发者可以在这个回调方法中做一些优化,防止被系统杀进程.目前用这个方法的情景并不多见,除非开发者想向下兼容的比较深.目前可以用onTrimMemory()
替代
- 调用时间:监听到系统内存很低的时刻
registerComponentCallbacks(object : ComponentCallbacks2 { override fun onLowMemory() { //Do something... } })复制代码
onTrimMemoey()
这个方法目前用来替代上面的onLowMemory()
方法.方法会传入一个level的Int参数,这是一个目前系统通知给App的一个内存不足等级,越高越严重.不同的等级系统会对App做出不同的操作.
内存不足级别 | 意义 |
---|---|
TRIM_MEMORY_RUNNING_MODERATE | 等级5:应用可以正常在前台运行,但是系统已经要开始杀后台进程了 |
TRIM_MEMORY_RUNNING_LOW | 等级10:应用可以正常在前台运行,但是系统通知释放资源,不然会影响速度 |
TRIM_MEMORY_RUNNING_CRITICAL | 等级15:前台运行,但是大部分后台被杀死,此时必须释放内存,不然此应用进程也会被杀死 |
TRIM_MEMORY_UI_HIDDEN | 等级20:系统会将该应用的UI资源收回,转为后台 |
TRIM_MEMORY_BACKGROUND | 等级40:此时应用处于LRU缓存列表的最近位置,需要立刻释放容易恢复的资源 |
TRIM_MEMORY_MODERATE | 等级60:此时应用处于LRU缓存列表的中间位置,有被杀死进程的危险 |
TRIM_MEMORY_COMPLETE | 等级80:非常危险的等级,应用处于缓存列表最边缘,即将被杀死 |
-
系统杀进程规则:
系统会按照LRU Cache列表由低到高杀进程,会优先杀占用内存较高的应用,也就是应用占用内存较小的话,被杀死的概率会降低.
-
使用方法:
override fun onTrimMemory(level: Int) { if (level in TRIM_MEMORY_RUNNING_MODERATE..(TRIM_MEMORY_RUNNING_LOW - 1)){ //Do something... }else if (level >= TRIM_MEMORY_RUNNING_LOW){ //Do something... }}复制代码
onConfigurationChanged()
-
作用:
监听APP的一些配置信息的改变事件(比如屏幕旋转)
-
调用时间:
当配置信息改变的时候会回调此方法
-
配置信息:
配置信息也就是
Manifest.xml
文件中Activity
中android:configChanges
属性的值,在该属性中填入android:configChanges="keyboardHidden|orientation|screenSize"
可以让屏幕旋转时不重启,而是执行onConfigurationChanged()
方法 -
使用方法:
registerComponentCallbacks(object : ComponentCallbacks2 { override fun onConfigurationChanged(newConfig: Configuration?) { //Do something }}复制代码
ActivityLifecycleCallbacks()
这是一个接口,可以通过registerActivityLifecycleCallbacks()
和unregisterActivityLifecycleCallbacks()
来注册/注销对所有Activity生命周期的监听,当Activity的生命周期发生改变的时候,就会调用接口里的方法.
- 使用方法
registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks { override fun onActivityPaused(activity: Activity?) { } override fun onActivityResumed(activity: Activity?) { } override fun onActivityStarted(activity: Activity?) { } override fun onActivityDestroyed(activity: Activity?) { } override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) { } override fun onActivityStopped(activity: Activity?) { } override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) { } })复制代码
这个主要就是对不同的生命周期进行监听,这里就不往里面写操作代码了.有兴趣的可以自己在里面加Log测试.
onTerminate()
在程序结束的时候会调用,只是用于仿真机的测试,真机上不会调用,没什么好说的.
registerOnProvideAssistDataListener()&unregisterOnProvideAssistDataListener()
这两个方法看名字是需要可以注册准备语音助手的数据的监听器,需要传入OnProvideAssistDataListener
接口对象,接口里只有一个onProvideAssistData(Activity activity,Bundle data)的方法,看官网的介绍是当用户启动语音助手时会构建一个Intent.ACTION_ASSIST.而且会附加用户请求帮助时的用户位置信息和上下文.
看网上的说法是国外的手机调用语音助手是会调用这个方法,我猜测应该不是国外手机,而是谷歌的语音助手,我用OxygenOS系统测试了一下,发现确实在呼出谷歌助手的时候调用了方法,Bundle不是空的,但是我也没找到里面的信息,应该是我的方法不对,我目前还没探究出这个方法要怎么用.如果有知道的大牛麻烦指导一下
- 我的测试:
registerOnProvideAssistDataListener { activity, data -> if (data == null) { Log.d("日志", "Bundle为空") } else { var string = "Bundle{" for (item in data.keySet()) { string += " $item => ${data.get(item)};" } string += "}Bundle" Log.d("日志",string) Log.d("日志","data is:$ACTION_ASSIST + $EXTRA_ASSIST_PACKAGE + $EXTRA_ASSIST_CONTEXT") startActivity(object :Intent(ACTION_ASSIST){}) }}复制代码
- 测试结果:
日志: Bundle{}Bundle日志: data is:android.intent.action.ASSIST + android.intent.extra.ASSIST_PACKAGE + android.intent.extra.ASSIST_CONTEXT复制代码
自定义Application
介绍完上面的方法,现在总算要开始自定义Application
类了,其实自定义Application类步骤并不多,下面来介绍一下.
-
创建继承自Application类的子类
这个就没什么说的了,直接看代码吧
class MyApplication : Application() { override fun onCreate() { super.onCreate() //DO something... }}复制代码
- 进入Manifest配置自定义类
复制代码
-
获取Application类的实例
获取实例的方法上面已经讲到了,这里就不赘述了.
作用
一般来说是不需要自定义Application类的,但是如果需要实现下面的功能,可以自定义Application类
- 初始化部分资源(全局对象,全局共享变量,方法等)
- 对内存占用进行优化
- 监听APP配置信息和所有Activity的生命周期