热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入解析Android中的Application类及其核心功能

本文出处:炎之铠csdn博客:http:blog.csdn.nettotond炎之铠邮箱:yanzhikai_yjk@qq.com本文原创,转载请注明本出处!前言

本文出处
炎之铠csdn博客:http://blog.csdn.net/totond
炎之铠邮箱:yanzhikai_yjk@qq.com
本文原创,转载请注明本出处!

前言

  最近的开发中经常使用到Application类,它的用处很多,但是网上的资料有很多是旧的或者是介绍不全的,在这里全面总结一下,先介绍Application的所有方法,再介绍它的使用经验。

本文基于Android6.0源码,API LEVEL 23。

介绍

  首先看看官网的介绍:

  下面是我对Application类的理解:

  • 每个APP都有一个Application实例:如果我们没有继承Application子类自定义它的话,APP会创建一个默认的实例。
  • Application实例拥有着与APP一样长的生命周期:在APP开启的时候首先就会实例化它,然后才是入口的Activity或者Service等。
  • Application与APP“同生共死”,在一个APP的生命周期只实例化一次,所以它“天生”就是一个单例,不需要使用单例模式去实现它。
  • 而上面的官方Note里面说到,通常是没有必要实现Application的子类的,要用单例的话可以自己使用静态单例类实现,要用它的Context的话用Context.getApplicationContext()就行了。然而,Application类的作用可不单单是实现一个全局的单例,还有其他的很多功能,下面一一介绍。

Application类功能

Application类的方法

  首先看看类结构:

  Application是继承自ContextWarpper的,继承来的方法就不在这里说了,下面来看看Application的方法:

onCreate()方法

  在Application创建的时候调用,一般用于初始化一些东西,如全局的对象,环境的配置等。

onConfigurationChanged(Configuration newConfig)方法

  重写此方法可以监听APP一些配置信息的改变事件(如屏幕旋转等),当配置信息改变的时候会调用这个方法。在Manifest文件下的Activity标签(注意是Activity)里配置android:configChanges属性相应的配置属性,会使Activity在配置改变时候不会重启,只会执行onConfigurationChanged()方法。如:android:cOnfigChanges="keyboardHidden|orientation|screenSize"属性可以使Activity旋转时不重启。

onLowMemory()方法

  重写此方法可以监听Android系统整体内存较低时候的事件。按我的理解就是,当APP处于前台时,但是所有后台程序都被kill光了,但是还是内存不足时,系统就会调用这个方法告诉APP,兄弟轮到你了。我们可以在这个方法里面释放一些不重要的资源,来保证到时候内存足够而让APP进程不被系统杀掉,或者提醒用户清一下垃圾,让内存清一点空位出来,我的手机老是这样提示我,不知道是不是这个方法惹的祸。

onTrimMemory(int level)方法

  这个方法是一个比较难理解的方法,Trim意思是修剪,按我的理解,用这个方法打个比方:
  从前有个伟大的妈妈叫Android系统,她有一群子女叫APP,她含辛茹苦地养着这群熊孩子。当系统老妈发现她的工资(内存)不够下个月的开销的时候,就会回调这个方法,告诉她的APP子女,我现在工资不够了,你们赶紧少吃少用点,不然我就要根据你们的重要性高低来一个一个地“清理门户”了。
  这里有传入一个int类型的参数level,它告诉APP们内存不足的严重性(越高越严重)。假如这时候系统内存不足,运行着前台和后台一共几个APP,这些不同的APP会收到系统老妈不同的“劝告信息”:

  • TRIM_MEMORY_RUNNING_MODERATE:数值为5,这个APP是系统老妈的“掌上明珠”(前台APP),老妈让APP注意一下:不要大手大脚(释放不用的内存),我的工资(内存)不够养你了,不过就算再不够,只是把你其他不争气兄弟姐妹(杀掉后台APP)清出家门,你注意一下吧。
  • TRIM_MEMORY_RUNNING_LOW:数值10,这个APP是系统老妈的“掌上明珠”(前台APP),老妈语重心长地对APP说:孩子,我的工资(内存)实在不够了,你能不能拿点压岁钱出来帮补一下(释放不用的内存),不行的话就要把你的很多兄弟姐妹(杀掉后台APP)送走了。
  • TRIM_MEMORY_RUNNING_CRITICAL:数值15,这个APP是系统老妈的“掌上明珠”(前台APP),老妈严重警告APP:臭小子,你的兄弟姐妹(杀掉后台APP)都快走光了,你还不给我多省点钱(要求释放内存),你还真的想把你的兄弟全赶走啊,当时候就剩你一个,说不定你都自身难保啦(执行onLowMemory()方法)。
  • TRIM_MEMORY_UI_HIDDEN:数值20,老妈告诉这个APP:你个熊孩子,闯了祸(用户把APP从前台切换到后台),我要收回你的零用钱(UI资源)。
  • TRIM_MEMORY_BACKGROUND :数值40,这些APP是老妈收养的(后台APP),老妈在吃完晚饭后留下了他,对他说:孩子啊,现在家里经济不好(内存不足),你就少花点吧,这个月的零用钱不发了吧(要求释放资源),不然的话我们家可能养不下你和你后面的那帮兄弟姐妹了(杀掉后台APP)。
  • TRIM_MEMORY_MODERATE :数值60,这些APP是老妈收养的(后台APP),老妈偷偷地跟APP说:孩子啊,你们花费太多了,老妈的工资养不下你们了(内存不足),你们用少点吧(要求释放内存),不然等我把你后面那几个兄弟赶出去之后就轮到你了(已进入LRU缓存列表的中间位置,如果后面的APP进程资源都被回收的话,下一个就是轮到它了)。
  • TRIM_MEMORY_COMPLETE :数值80,这些APP是老妈充话费送的(后台APP),老妈狠狠地对他说:臭小子,没看到都快揭不开锅了(内存不足)吗?赶紧把你的私房钱拿出来(要求释放资源),不然你们就准备滚出这个家门吧(已处于LRU缓存列表的后面位置,APP随时都有被回收的风险)。

    说了这么多其实实际上这个方法有什么用呢?我目前想到的系统用这个方法提醒APP释放一些缓存了,如图片缓存,数据缓存之类的。
    这篇文章很详细的讲述了这个方法。

onTerminate()方法

  这个方法在程序结束的时候会调用。但是这个方法只用于Android仿真机测试的时候,在Android产品机是不会调用的。所以这个方法并没什么用。

registerActivityLifecycleCallbacks()和unregisterActivityLifecycleCallbacks()

  这两个方法用于注册或者注销对APP内所有Activity的生命周期监听,当APP内Activity的生命周期发生变化的时候就会调用ActivityLifecycleCallbacks里面的方法:

        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Log.d(TAG,"onActivityCreated: " + activity.getLocalClassName());
}

@Override
public void onActivityStarted(Activity activity) {
Log.d(TAG,"onActivityStarted: " + activity.getLocalClassName());
}

@Override
public void onActivityResumed(Activity activity) {
Log.d(TAG,"onActivityResumed: " + activity.getLocalClassName());
}

@Override
public void onActivityPaused(Activity activity) {
Log.d(TAG,"onActivityPaused: " + activity.getLocalClassName());
}

@Override
public void onActivityStopped(Activity activity) {
Log.d(TAG, "onActivityStopped: " + activity.getLocalClassName());
}

@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}

@Override
public void onActivityDestroyed(Activity activity) {
Log.d(TAG,"onActivityDestroyed: " + activity.getLocalClassName());
}
});

我们来测试一下,把APP切到后台再打开,log结果是:

 onActivityPaused: MainActivity
onActivityStopped: MainActivity
onActivityStarted: MainActivity
onActivityResumed: MainActivity

registerComponentCallbacks()和unregisterComponentCallbacks()方法

  用于注册和注销ComponentCallbacks2回调接口,里面的方法前面已经介绍过,看名字就知道:

        registerComponentCallbacks(new ComponentCallbacks2() {
@Override
public void onTrimMemory(int level) {

}

@Override
public void onConfigurationChanged(Configuration newConfig) {

}

@Override
public void onLowMemory() {

}
});

  Context类也有这两个方法,但是Context类的方法只可以使用ComponentCallbacks,比Application少了一个onTrimMemory()回调。

registerOnProvideAssistDataListener()和unregisterOnProvideAssistDataListener()方法

  API18以上的方法,网上关于这两个方法的介绍很少,几乎没有,在官网上的介绍是这样的:

This is called when the user is requesting an assist, to build a full ACTION_ASSIST Intent with all of the context of the current application.

  好像是当用户请求帮助的时候会调用这个方法,然后会启动一个ACTION_ASSIST的Intent。什么时候才是用户请求帮助呢?StackOverflow里有的人说是长按Home键,外国的机子会跳出Google Now这个助手,至于国内的机子,我用我自己的华为荣耀6P长按Home键是弹出语音助手,但是没有回调这个方法。然后尝试了一下用下面的代码来发送一个ACTION_ASSIST来看看有什么效果:

        Intent intent = new Intent(ACTION_ASSIST);
context.startActivity(intent);

  结果打开了我手机上UC浏览器的语音搜索功能。。。
  最后还是搞不懂这个方法什么时候会回调,如果有知道的请告知,谢谢!

Application类的使用

  要使用自定义的Application,首先就是要自己新建一个Application的子类,然后把它的名字写在manifest文件里面的application标签里的android:name属性就行,如我的Application子类名字是BaseApplication,则:

     android:name=".BaseApplication"

1.初始化资源

  由于Application类是在APP启动的时候就启动,启动在所有Activity之前,所以可以使用它做资源的初始化操作,如图片资源初始化,WebView的预加载,推送服务的注册等等,注意不要执行耗时操作,会拖慢APP启动速度。

2.数据全局共享

  • 可以设置一些全局的共享常量,如一些TAG,枚举值等。
  • 可以设置一些全局使用的共享变量数据,如一个全局的Handler等等,但是要注意,这里缓存的变量数据的作用周期只在APP的生命周期,如果APP因为内存不足而结束的话,再开启这些数据就会消失,所以这里只能存储一些不重要的数据来使数据全APP共享,想要储存重要数据的话需要SharePreference、数据库或者文件存储等这些本地存储。
  • 可以设置一些静态方法来让其他类调用,来使用Application里面的全局变量,如实现APP一键退出功能时候会用到。

后话

  以上就是我对Android中Application的总结和使用经验,基于Android6.0的API,所有的方法都是经过实测的,如有错漏,敬请指正,谢谢!

参考文章

https://developer.android.com/reference/android/app/Application.html
http://blog.csdn.net/man_embedded/article/details/52625619
http://androidperformance.com/2015/07/20/Android-Performance-Memory-onTrimMemory.html
http://blog.csdn.net/android_jianbo/article/details/46228003


推荐阅读
  • 深入理解 .NET 中的中间件
    中间件是插入到应用程序请求处理管道中的组件,用于处理传入的HTTP请求和响应。它在ASP.NET Core中扮演着至关重要的角色,能够灵活地扩展和自定义应用程序的行为。 ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • 本文详细介绍了SDCMS中的全局标签和循环标签。全局标签是在任何模板页面中均可调用的标签,而循环标签用于数据查询和展示。文章解释了这些标签的功能、使用方法及参数配置。 ... [详细]
  • 本文详细介绍了优化DB2数据库性能的多种方法,涵盖统计信息更新、缓冲池调整、日志缓冲区配置、应用程序堆大小设置、排序堆参数调整、代理程序管理、锁机制优化、活动应用程序限制、页清除程序配置、I/O服务器数量设定以及编入组提交数调整等方面。通过这些技术手段,可以显著提升数据库的运行效率和响应速度。 ... [详细]
  • Java项目分层架构设计与实践
    本文探讨了Java项目中应用分层的最佳实践,不仅介绍了常见的三层架构(Controller、Service、DAO),还深入分析了各层的职责划分及优化建议。通过合理的分层设计,可以提高代码的可维护性、扩展性和团队协作效率。 ... [详细]
  • 在 Android 开发中,通过 Intent 启动 Activity 或 Service 时,可以使用 putExtra 方法传递数据。接收方可以通过 getIntent().getExtras() 获取这些数据。本文将介绍如何使用 RoboGuice 框架简化这一过程,特别是 @InjectExtra 注解的使用。 ... [详细]
  • 本文将详细介绍多个流行的 Android 视频处理开源框架,包括 ijkplayer、FFmpeg、Vitamio、ExoPlayer 等。每个框架都有其独特的优势和应用场景,帮助开发者更高效地进行视频处理和播放。 ... [详细]
  • 离线安装Grafana Cloudera Manager插件并监控CDH集群
    本文详细介绍如何离线安装Cloudera Manager (CM) 插件,并通过Grafana监控CDH集群的健康状况和资源使用情况。该插件利用CM提供的API接口进行数据获取和展示。 ... [详细]
  • 深入解析Spring启动过程
    本文详细介绍了Spring框架的启动流程,帮助开发者理解其内部机制。通过具体示例和代码片段,解释了Bean定义、工厂类、读取器以及条件评估等关键概念,使读者能够更全面地掌握Spring的初始化过程。 ... [详细]
  • 本文介绍了解决Oracle 10G数据库中ORA-12541 TNS: no listener错误的详细步骤。该错误通常发生在监听器服务未正确启动或配置不当的情况下,文章将指导您通过检查服务状态、配置注册表和启动监听器来解决问题。 ... [详细]
  • 本文详细介绍了 Python 中的条件语句和循环结构。主要内容包括:1. 分支语句(if...elif...else);2. 循环语句(for, while 及嵌套循环);3. 控制循环的语句(break, continue, else)。通过具体示例,帮助读者更好地理解和应用这些语句。 ... [详细]
  • ssm框架整合及工程分层1.先创建一个新的project1.1配置pom.xml ... [详细]
  • 并发编程 12—— 任务取消与关闭 之 shutdownNow 的局限性
    Java并发编程实践目录并发编程01——ThreadLocal并发编程02——ConcurrentHashMap并发编程03——阻塞队列和生产者-消费者模式并发编程04——闭锁Co ... [详细]
  • 本文详细介绍了如何在云服务器上配置Nginx、Tomcat、JDK和MySQL。涵盖从下载、安装到配置的完整步骤,帮助读者快速搭建Java Web开发环境。 ... [详细]
  • 基于Node.js、Express、MongoDB和Socket.io的实时聊天应用开发
    本文详细介绍了使用Node.js、Express、MongoDB和Socket.io构建的实时聊天应用程序。涵盖项目结构、技术栈选择及关键依赖项的配置。 ... [详细]
author-avatar
mobiledu2502859507
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有