导读
- 移动开发知识体系总章(Java基础、Android、Flutter)
- Application是什么
- Application生命周期
- 使用Application传递数据
- 使用Application数据缓存
- Application的context
- Application的oncreate方法会执行几次,会不会多次执行?
- 使用Application避免一些内存泄漏
Application是什么
Application和Activity、Service一样是Android框架的一个系统组件,当Android程序启动时系统会创建一个 Application对象,用来存储系统的一些信息。
Application的生命周期等于这个程序的生命周期,又因为Application是全局的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以通过Application来进行一些数据传递、数据共享、数据缓存等操作。
一般写Demo是不需要指定一个Application的,这时系统会自动帮我们创建;而实际项目中基本上都是需要创建自己的Application的,创建一个类继承 Application并在AndroidManifest清单文件中的Application标签中进行注册(只需要给Application标签增加个name属性把自己的 Application的名字定入即可)。android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application可以说是单例 (singleton)模式的一个类。
Application生命周期
- onConfigurationChanged( ) :在配置被改变时触发 。
- onCreate() :在程序创建时创建。
- onLowMemory() :内存不够时触发。
- onTerminate() :当终止程序时调用 但是不能保证一定调用
- onTrimMemory() :在内存清理时触发
public class App extends Application {
@Override
public void onCreate() {
// 程序创建的时候执行
Log.d(TAG, "onCreate");
super.onCreate();
}
@Override
public void onTerminate() {
// 程序终止的时候执行
Log.d(TAG, "onTerminate");
super.onTerminate();
}
@Override
public void onLowMemory() {
// 低内存的时候执行
Log.d(TAG, "onLowMemory");
super.onLowMemory();
}
@Override
public void onTrimMemory(int level) {
// 程序在内存清理的时候执行
Log.d(TAG, "onTrimMemory");
super.onTrimMemory(level);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
Log.d(TAG, "onConfigurationChanged");
super.onConfigurationChanged(newConfig);
}
}
使用Application传递数据
在android中通常会使用Intent(Bundle)进行数据通信,但一般为简单数据类型,如数据类型相对复杂(如对象)则需要实现 Serializable或者Parcelable接口,其实可以使用Application传递复杂数据。
基本思路是这样的。在Application中创建一个HashMap ,以字符串为key,Object为value这样我们的HashMap就可以存储任何类型的对象了
使用Application数据缓存
既然可以在Application中使用HashMap 进行传递数据,自然是可以进行一些缓存动作了,不过笔者基本没有这样操作过,同时需要注意内存泄漏。
Application的Context
- Context是一个应用程序环境的信息,即上下文。
- 该类是一个抽象(abstract class)类,Android提供了该抽象类的具体实现类(后面我们会讲到是ContextIml类)。
-
通过它我们可以获取应用程序的资源和类,也包括一些应用级别操作,例如:启动一个Activity,发送广播,接受Intent信息 等
可以看到Activity、Service、Application都是Context的子类。
也就是说,Android系统的角度来理解:Context是一个场景,代表与操作系统的交互的一种过程。从程序的角度上来理解:Context是个抽象类,而Activity、Service、Application等都是该类的一个实现。
Application的oncreate方法会执行几次,会不会多次执行?
通常情况下,App默认开启一个进程,进程名就是AndroidManifest.xml文件中我们项目的包名,所有的基本组件都是在这个进程中进行,Application的onCreate方法会被执行一次
。但是如果我们工程涉及到多进程,那么就会出现Application的onCreate方法被多次执行
情况。
解决oncreate方法多次被调用:
1、定义获取进程的方法
private String getProcessName(Context context) {
try {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List runningApps = am.getRunningAppProcesses();
if (runningApps == null) {
return null;
}
for (ActivityManager.RunningAppProcessInfo proInfo : runningApps) {
if (proInfo.pid == android.os.Process.myPid()) {
if (proInfo.processName != null) {
return proInfo.processName;
}
}
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
2、在onCreate方法中进行比对
@Override
public void onCreate() {
super.onCreate();
String processName = getProcessName(this);
if (processName!= null) {
String pkName = this.getPackageName();
//只有主进程,才执行后续逻辑
if(processName.equals(pkName)==false) {
return;
}
}
使用Application避免一些内存泄漏(Memory Leak)
在Java中内存泄漏是指某个(某些)对象已经不在被使用应该被GC回收,但有一个对象持有这个对象的引用而阻止这个对象被回收。
比如在项目中经常用到单例模式,而很多单例是需要传递Context的,由于sInstance是一个static且强引用的,若此时传递Context的是xxxActivity.this,那么这个xxxActivity就不会被内存回收,就会造成内存泄漏。
解决办法就是Context传递context.getApplicationContext()
ps 经常导致内存泄漏核心原因分析(跳转连接)
以下内容等待被编辑到指定位置
ps 经常导致内存泄漏核心原因分析(跳转连接)
keeping a long-lived reference to a Context
上述是常见的内存泄漏的提示,即持有一个context的对象,从而GC不能回收,为什么会有这样的情况呢
- 一个View的作用域超出了所在的Activity的作用域,比如一个static的View或者把一个View cache到了application
- 某些与View关联的Drawable的作用域超出了Activity的作用域.
- Runnable对象:比如在一个Activity中启用了一个新线程去执行一个任务,在这期间这个Activity被系统回收了, 但Runnalbe的 任务还没有执行完毕并持有Activity的引用而泄漏,但这种泄漏一般来泄漏一段时间,只有Runnalbe的线程执行完闭,这个 Activity又可以被正常回收了。
- 内存类的对象作用域超出Activity的范围:比如定义了一个内存类来存储数据,又把这个内存类的对象传给了其它Activity、Service等。因为内部类的对象会持有当前类的引用,所以也就持有了Context的引用。
解决方法是如果不需要当前的引用把内部类写成static或者把内部类抽取出来变成一个单独的类,或者作用域超出Activity的作用域。
Out Of Memery Error 在Android中每一个程序所分到的内存大小是有限的,如果超过了这个数就会报Out Of Memory Error。 Android给程序分配的内存大小与手机硬件有关,以下是一些手机的数据:
G1:16M Droid:24 Nexus One:32M Xoom:48Ms
所以尽量把程序中的一些大的数据cache到本地文件。以免内存使用量超标。
记得数据传递完成之后,把存放在application的HashMap中的数据remove掉,以免发生内存的泄漏。