Application在一个Dalvik虚拟机里只会存在一个实例。为什么强调一个Dalvik虚拟机,而不是说一个App呢?
因为一个App可能有多个Dalvik虚拟机,也就是多进程模式。在这种模式下,每一个Dalvik都会存在一个Application实例,他们之间没有关系,在A进程Application里保存的数据不能在B进程的Application获取,因为根本就不是一个对象,而且被隔离在两个进程里,所以强调一个Dalvik虚拟机,而不是一个app。
App中谁的传递可能是session token等,避免Activity之间传递数据开销,会讲这些数据通过持久化来存储。有人建议在Application中存储,这个完全错误,程序最终可能会导致一个NullPointerException异常崩溃。不论是public static还是其他成员变量都是不行的。
A-->Activty
B-->Activty
Application 成员定义个name(随便怎么修饰、public static等)
1、A界面对Application的name设值,然后跳转到B界面。
2、当B界面点击home键回到后台,过了若干小时,系统由于内存不足(用户在体验其它APP呢,前台的任务总是优先的嘛)会在后台将你的程序杀掉;在你重新启动该APP之前一切看上去很好,再点击应用图标回到前台,但是....
3、用户重新打开了这个APP;
4、Android会重新创建一个之前被Kill掉的MyApplication实例并恢复B
5、B去获取用户名时,会因为获取的为空值报NullPointerException而崩溃掉
为什么会这样?
程序之所以crash,因为恢复后的App的Application对象是全新的,所以缓存在Application中的变量为空。
导致这个问题的主要原因:Application对象并不是始终在内存中的,它可能会由于系统内存不足而被杀死。但Android在你恢复这个应用时并不是重新开始启动这个应用,他会创建一个新的Application对象,并启动上次用户离开时的activity以造成这个app从来没有被kill掉的假象。
我们可以通过Application缓存数据,却没想到恢复App时直接跑到了B而不是先启动A,最终导致结果程序的意外crash。
替代方案?
通过Intent在Activity之间传递数据(传递大量数据,有可能异常或者ANR)
使用官方推荐的数据持久化,存储在磁盘中
在使用数据的时候进行空值检测
如何模拟应用程序被杀掉?
最简单的是DDMS中点击“Stop Process”杀掉程序。通过模拟器或者一个Root真机测试。
1、按Home键退出程序
2、控制台输入
找到app的包名packageName
adb shell ps
找到应用的pid
adb shell ps | grep packageName
杀死pid
adb shell kill -9 pid
3、长按home键后台任务管理打开App,会重新创建一个MyApplication实例了。
总结:
并不仅仅只有Application这样,其它单例或者公有静态勒也会由于系统内存而被杀掉。
网友评论