Android-Application详解

4,995 阅读6分钟

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文件中Activityandroid: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
         android:name=".MyApplication"            
</application>
  • 获取Application类的实例

    获取实例的方法上面已经讲到了,这里就不赘述了.

作用

一般来说是不需要自定义Application类的,但是如果需要实现下面的功能,可以自定义Application类

  • 初始化部分资源(全局对象,全局共享变量,方法等)
  • 对内存占用进行优化
  • 监听APP配置信息和所有Activity的生命周期