千万不要把数据存储在Application对象中
2013-06-08 19:52
363 查看
译自:http://www.developerphil.com/dont-store-data-in-the-application-object/
在我们的应用程序中有些数据需要在多处使用。有可能是一个会话令牌,花费很大代价才得来的结果,等等。而且我们总是想避免在两个Activity之间传递数据或者不想把数据存储在持久存储器中。
一个解决问题的模式是把数据存储在应用的Application对象中,这样呢存储的数据就能在所有的Activity中共享。这种解决办法看起来很简单,很优雅,但其实是错误的!
如果你始终相信数据一直会待在Application对象中,那么你的应用最终会因为NullPointerException异常而终止。
The first activity, where we store the name of the user in the application object:
The second activity, where we shout the name of the user:
2、在WhatIsYourNameActivity中,你把用户的名字存储在MyApplication对象中
3、在GreetLoudlyActivity中,你从MyApplication对象中把用户的名字提取出来并显示给用户
4、用户按下home键离开了你的应用
5、在几个小时后,Android可能会在后台默默地把你的应用杀死,释放内存给其它应用使用
到目前为止并不会出现啥问题,你的应用也没有出现任何异常
6、用户重新打开了你的应用
7、Android会重新创建一个MyApplication对象和恢复GreeLoudlyActivity
8、GreetLoudlyActivity获取用户的名字,但现在用户名字已经是null,你的应用抛出NullPointerException异常终止
String#toUpperCase()
导致NullPointerException
发生问题的核心:Application对象不会永远存在于内存中,可能会被回收杀死。普遍的看法是应用不会从头重新启动。Android会创建一个新的Application对象并且恢复之前的Activity,给用户一个错觉是应用永远都不会被杀死,一直停留在原先的状态
这意味着如果你期待用户不会在打开Activity A之前打开Activity B,数据一直会在Application对象中。那么你会得到一个异常终止的惊喜!
1、使用intent明确的在Activity之间传递数据
2、使用
many ways 中的一种来在磁盘上存储数据
3、总是手动来进行null-check
要测试这个,你必须需要有一个模拟器或一台root过的手机
1、使用home键来退出你的应用
2、在命令行敲入如下命令
3、使用任务切换功能重新回到你的应用,现在你的应用就重新创建了Application对象
如果数据在后面会被使用到,你可以存储在磁盘中或者通过
intent’s extras传递到需要的Activity中
另外还要注意的是对于Application对象来说是这种情况,那么对于任何单例对象或者静态属性来说都如此
注:经过自己的测试,确实出现如作者所描述的情况
千万不要把数据存储在Application对象中
may 5, 2013在我们的应用程序中有些数据需要在多处使用。有可能是一个会话令牌,花费很大代价才得来的结果,等等。而且我们总是想避免在两个Activity之间传递数据或者不想把数据存储在持久存储器中。
一个解决问题的模式是把数据存储在应用的Application对象中,这样呢存储的数据就能在所有的Activity中共享。这种解决办法看起来很简单,很优雅,但其实是错误的!
如果你始终相信数据一直会待在Application对象中,那么你的应用最终会因为NullPointerException异常而终止。
一个很简单的测试案例
The Application object:// access modifiers omitted for brevity classMyApplication extends Application { String name; String getName() { returnname; } voidsetName(String name) { this.name = name; } }
The first activity, where we store the name of the user in the application object:
// access modifiers omitted for brevity classWhatIsYourNameActivity extends Activity { voidonCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.writing); // Just assume that in the real app we would really ask it! MyApplication app = (MyApplication) getApplication(); app.setName("Developer Phil"); startActivity(newIntent(this, GreetLoudlyActivity.class)); } }
The second activity, where we shout the name of the user:
// access modifiers omitted for brevity classGreetLoudlyActivity extends Activity { TextView textview; voidonCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.reading); textview = (TextView) findViewById(R.id.message); } voidonResume() { super.onResume(); MyApplication app = (MyApplication) getApplication(); textview.setText("HELLO " + app.getName().toUpperCase()); } }
用户使用你应用可能的场景
1、用户打开你的应用2、在WhatIsYourNameActivity中,你把用户的名字存储在MyApplication对象中
3、在GreetLoudlyActivity中,你从MyApplication对象中把用户的名字提取出来并显示给用户
4、用户按下home键离开了你的应用
5、在几个小时后,Android可能会在后台默默地把你的应用杀死,释放内存给其它应用使用
到目前为止并不会出现啥问题,你的应用也没有出现任何异常
6、用户重新打开了你的应用
7、Android会重新创建一个MyApplication对象和恢复GreeLoudlyActivity
8、GreetLoudlyActivity获取用户的名字,但现在用户名字已经是null,你的应用抛出NullPointerException异常终止
为什么会异常终止
在例子程序中,由于Application对象是新创建出来的,name属性为null,调用String#toUpperCase()
导致NullPointerException
发生问题的核心:Application对象不会永远存在于内存中,可能会被回收杀死。普遍的看法是应用不会从头重新启动。Android会创建一个新的Application对象并且恢复之前的Activity,给用户一个错觉是应用永远都不会被杀死,一直停留在原先的状态
这意味着如果你期待用户不会在打开Activity A之前打开Activity B,数据一直会在Application对象中。那么你会得到一个异常终止的惊喜!
解决办法
这里没有很好的解决方案,但是你可以遵循以下一些准则:1、使用intent明确的在Activity之间传递数据
2、使用
many ways 中的一种来在磁盘上存储数据
3、总是手动来进行null-check
怎样来模拟应用程序被杀
EDIT:Daniel Lew 指出一个最简单的方法是在DDMS中使用“Stop Process”功能来杀死一个应用(设备在debug模式)要测试这个,你必须需要有一个模拟器或一台root过的手机
1、使用home键来退出你的应用
2、在命令行敲入如下命令
# find the process id adb shell ps # then find the line with the package name of your app # Mac/Unix: save some time by using grep: adb shell ps | grep your.app.package # The result should look like: # USER PID PPID VSIZE RSS WCHAN PC NAME # u0_a198 21997 160 827940 22064 ffffffff 00000000 S your.app.package # Kill the app by PID adb shell kill -9 21997 # the app is now killed
3、使用任务切换功能重新回到你的应用,现在你的应用就重新创建了Application对象
总结
在Application对象中存储数据容易出错,让你的应用异常终止如果数据在后面会被使用到,你可以存储在磁盘中或者通过
intent’s extras传递到需要的Activity中
另外还要注意的是对于Application对象来说是这种情况,那么对于任何单例对象或者静态属性来说都如此
注:经过自己的测试,确实出现如作者所描述的情况
相关文章推荐
- Android开发之千万不要把数据存储在Application对象中
- 千万不要在Android的Application对象中缓存数据!
- Android中的Application对象里尽量不要存储数据
- 不要在Android的Application对象里存储数据
- 不要在Android的Application对象中缓存数据!
- 不要在Android的Application对象中缓存数据!
- 为什么不能往Android的Application对象里存储数据
- 不要在Android的Application对象中缓存数据!
- 往Android的Application对象里存储数据的陷阱
- 不要在Android的Application对象中缓存数据!
- Application对象中存储的数据一直存在?
- 不要在Android的Application对象中缓存数据
- 为什么不能往Android的Application对象里存储数据
- Application对象所存储的 数据如何清空
- 为什么不能往Android的Application对象里存储数据
- 为什么不能往Android的Application对象里存储数据
- 往Android的Application对象里存储数据的陷阱
- 为什么不能往Android的Application对象里存储数据
- 【Android】不要在Application对象中缓存数据!
- 为什么不能往Android的Application对象里存储数据