android-application学习
-
介绍:
Application
是单例模式的类,android
系统为每个应用程序创建一个Application
类的对象且只创建一个。
启动Application
时,系统会创建一个PID,即进程ID,所有的Activity
都会在此进程上运行。
Application
创建的时候初始化全局变量,同一个应用的所有Activity
都可以取到这些全局变量的值
Application
对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期
Application
全局的单例的,所以在不同的Activity,Service
中获得的对象都是同一个对象
-
应用领域:数据传递、数据共享和数据缓存等操作。
- 复杂数据的传递:
-
Activity A,
跳转到Activity B
,用Intent.putExtra()
或者Bundle
进行传递数据,但是:Intent和Bundle
所能携带的数据类型都是一些基本的数据类型,想实现复杂的数据传递就比较麻烦了,通常需要实现Serializable
或者Parcellable接口
- 用
Application
进行解决:(思路)
在Application
中创建一个HashMap
,以字符串为索引,Object
为value这样我们的HashMap
就可以存储任何类型的对象了。在Activity A
中把需要传递的对象放入这个HashMap
,然后通过Intent
或者其它途经再把这索引的字符串传递给Activity B
,Activity B
就可以根据这个字符串在HashMap
中取出这个对象了。只要再向下转个型 ,就实现了对象的传递。
-
- 复杂数据的传递:
-
生命周期
-
onCreate
在创建应用程序时创建 -
onTerminate
当终止应用程序对象时调用,不保证一定被调用,当程序是被内核终止以便为其他应用程序释放资源,那么将不会提醒,并且不调用应用程序的对象的onTerminate
方法而直接终止进 程 -
onLowMemory
当后台程序已经终止资源还匮乏时会调用这个方法。好的应用程序一般会在这个方法里面释放一些不必要的资源来应付当后台程序已经终止,前台应用程序内存还不够时的情况。onConfigurationChanged
配置改变时触发这个方法 -
备注:
application 被杀死的情况分析
:(Application
的生命周期代表这个应用的生命周期)
为了决定在内存较低的时候杀掉哪个进程, Android会根据运行在这些进程内的组件及他们的状态把进程划分成一个”重要程度层次”. 其重要的程度按以下规则排序:- 1:前端进程可以是一个持有运行在屏幕最前端并与用户交互的Activity的进程(onResume方法被调用时),也可以是持有一个正在运行的IntentReceiver(也就是说他正在执行自己的onReceiveIntent方法)的进程. 在系统中, 只会有少数这样的进程, 并且除非内存已经低到不够这些进程运行, 否则系统不会主动杀掉这些进程. 这时, 设备通常已经达到了需要内存整理的状态, 所以杀掉这些进程是为了不让用户界面停止响应.
- 2:可视进程是持有一个被用户可见, 但没有显示在最前端 (onPause方法被调用时) 的Activity的进程. 举例来说, 这种进程通常出现在一个前端Activity以一个对话框出现并保持前一个Activity可见时. 这种进程被系统认为是极其重要的, 并且通常不会被杀掉, 除非为了保持所有前端进程正常运行不得不杀掉这些可见进程.
- 3:服务进程是持有一个Service的进程, 该Service是由startService()方法启动的, 尽管这些进程用户不能直接看到, 但是通常他们做的工作用户是十分关注的(例如, 在后台播放mp3或是在后台下载 上传文件), 所以, 除非为了保持所有的前端进程和可视进程正常运行外, 系统是不会杀掉服务进程的.
- 4:后台进程是持有一个不再被用户可见的Activity(onStop()方法被调用时)的进程. 这些进程不会直接影响用户体验. 加入这些进程已经完整的,正确的完成了自己的生命周期(访问Activity查看更多细节), 系统会在为前三种进程释放内存时随时杀掉这些后台进程. 通常会有很多的后台进程在运行, 所以这些进程被存放在一个LRU列表中, 以保证在低内存的时候, 最近一个被用户看到的进程会被最后杀掉.
- 5:空进程是没有持有任何活动应用组件的进程. 保留这种进程的唯一理由是为了提供一种缓存机制, 缩短他的应用下次运行时的启动时间. 就其本身而言, 系统杀掉这些进程的目的是为了在这些空进程和底层的核心缓存之间平衡整个系统的资源. 来自:
www.2cto.com
- 当需要给一个进程分类的时候, 系统会在该进程中处于活动状态的所有组件里掉选一个重要等级最高作为分类依据. 查看Activity, Service,和IntentReceiver的文档, 了解每个组件在进程整个生命周期中的贡献. 每一个classes的文档详细描述他们在各自应用的生命周期中所起得作用.
-
实现步骤:
1.继承Application
public class CustomApplication extends Application{
@Override
public void onCreate(){}
}
继承Application类
,主要重写里面的onCreate()
方法(android.app.Application包的onCreate()才是真正的Android程序的入口点)
2.在AndroidManifest.xml
文件中配置自定义的Application
<application
android:name="CustomApplication">
</application>
-
如何获得
Application
的信息(全局变量)呢?public class FirstActivity extends Activity{ private CustomApplication app; @Override public void onCreate(Bundle savedInstanceState){ ..... app = (CustomApplication) getApplication(); // 获得CustomApplication对象 Log.i("FirstActivity", "初始值=====" + app.getValue()); // 获取进程中的全局变量值,看是否是初始化值 app.setValue("Harvey Ren"); // 重新设置值 Log.i("FirstActivity", "修改后=====" + app.getValue()); // 再次获取进程中的全局变量值,看是否被修改 } }
只需要调用Context
的 getApplicationContext
或者Activity的getApplication方法
来获得一个Application对象,然后再得到相应的成员变量即可。
-
知识延伸:
MemoryLeak
在Java中内存泄漏是指:某个(某些)对象已经不在被使用应该被gc所回收,但有一个对象持有这个对象的引用而阻止这个对象被回收。比如我们通常会这样创建一个View TextView tv = new TextView(this);
这里的this
通常都是Activity
。所以这个TextView
就持有着这个Activity的引用。
通常情况下,当用户转动手机的时候,android会重新调用OnCreate()
方法生成一个新的Activity,原来的 Activity应该被GC所回收。但如果有个对象比如一个View的作用域超过了这个Activity(比如有一个static
对象或者我们把这个 View
的引用放到了Application
当中),这时候原来的Activity将不能被GC所回收,Activity
本身又持有很多对象的引用,所以 整个Activity的内存被泄漏了。
备注:经常导致内存泄漏核心原因:
keeping a long-lived reference to a Context.持有一个context的对象,从而gc不能回收。
- 1.**一个View的作用域超出了所在的Activity的作用域**,比如一个static的View或者把一个View cache到了application当中 etc
理解:内存:注意静态的数据和缓存中的数据;注意释放;
- 2.某些与View关联的Drawable的作用域超出了Activity的作用域。
- 3.Runnable对象:比如在一个Activity中启用了一个新线程去执行一个任务,在这期间这个Activity被系统回收了, 但Runnalbe的 任务还没有执行完毕并持有Activity的引用而泄漏,但这种泄漏一般来泄漏一段时间,只有Runnalbe的线程执行完闭,这个 Activity又可以被正常回收了。
- 4.内存类的对象作用域超出Activity的范围:比如定义了一个内存类来存储数据,又把这个内存类的对象传给了其它Activity 或者Service等。因为内部类的对象会持有当前类的引用,所以也就持有了Context的引用。解决方法
是如果不需要当前的引用把内部类写成static或者,把内部类抽取出来变成一个单独的类,或者把避免内部对象作用域超出Activity的作用域。
out Of Memery Error
在android中每一个程序所分到的内存大小是有限的,如果超过了这个数就会报Out Of Memory Error
。
- 注意:所以尽量把程序中的一些大的数据cache到本地文件。以免内存使用量超标。记得数据传递完成之后,把存放在application的HashMap中的数据remove掉
,以免发生内存的泄漏。
-
参考资料:
Android中Application类用法
android application 详解--深入浅出,讲解完整的Application,以及所涉及到的扩展知识。
Android笔记 Application对象的使用-数据传递以及内存泄漏问题