本文出自 “双门M” 简书博客,转载或引用请注明出处。
先上结论:
* 1、尽量不要往Application里面存放缓存数据(因为app用application缓存且使用全局数据,当这个app为后台程序时又被系统gc回收后我们再次打开app,就会导致空指针)
- 2、app被gc回收后再点击该app打开的会是回收前最后可见的activity(比如我们 app甲先后依次打开了a,b,c这三个activity,这时a,b,c都是在同一个线程的,这时我们按下home键,利用MMDS强制关闭我们程序甲的process,其实也就是模拟被gc回收了。这个时候我们在打开程序甲,会发现打开的是程序甲这的c这个activity,这个时候c是在一个新的线程里面的,而不是在原来的线程里面的)
有图有真相。
下图演示因为当安卓app被系统gc回收后我们再次打开app产生空指针导致数据丢失的现象
上图程序没挂是因为我们缓存在application的值我们这是用作显示,null就是空了,当我们使用了这个值马上程序就会应为空指针而挂掉。
下面我们使用以下给gc回收的缓存在application的值
一、不要往Application存缓存数据
当然这不是绝对化,只是这么建议。
在你的App中的很多地方都需要使用到数据信息,它可能是一个session token,一次费时计算的结果等等,通常为了避免Activity之间传递数据的开销,会将这些数据通过持久化来存储。
有人建议将这些数据放在Application对象中方便所有的Activity访问,这个解决方案简单、优雅并且是……完全错误的。
你如果你将数据缓存到Application对象中,那么有可能你的程序最终会由于一个NullPointerException异常而崩溃掉。
1、数据存在Application被gc后数据丢失的demo演示
下面通过demo演示因为数据存放在application导致数据丢失的情况:
1、新建一个类MyApplication继承自Application,弄一个那么的属性设置对应的get和set方法,并且让我们的程序的清单文件的application采用我们的MyApplication
2、弄三个acitivity,MainActivity有一个按钮,点击则打开FirstActivity,而Activity的onCreate方法干的事就是给MyApplicatipn的name属性set一个值,比如“Try Text”,接着就直接打开我们的SecondActivity
3、SecondAcrivity直接有一个TextView控件,这个控件用于显示从MyApplication取出来的那么的值。
嗯就是这样子,正常情况下,我们进入MainActivity,点击 “打开FirstActivity” 只会就进入FirstActivity之后瞬间进入SecondActivity。SecondActivity正常显示FirstActivity给存储在MyApplication里面的值。
这个是没什么问题的。这个时候,我们按下home键,然后利用DDMS把当前app杀掉(模拟给gc回收),然后在打开app,会发现SecondActivity显示的name值变为null,数据丢失了。一旦使用这个值就报空指针。
接下来贴一些代码:
MyApplication
public class MyApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
}
String name;
public String getName() {
return name;
}