前言

  在你的App中的很多地方都需要使用到数据信息,它可能是一个session token,一次费时计算的结果等等,通常为了避免Activity之间传递数据的开销,会将这些数据通过持久化来存储。

  有人建议将这些数据放在Application对象中方便所有的Activity访问,这个解决方案简单、优雅并且是……完全错误的。

  你如果你将数据缓存到Application对象中,那么有可能你的程序最终会由于一个NullPointerException异常而崩溃掉。

一个简单的测试程序

  这是自定义Application的代码:

// access modifiers omitted for brevity
class MyApplication extends Application { String name; String getName() {
return name;
} void setName(String name) {
this.name = name;
}
}

  在第一个Activity中,我们将用户信息存储在Application对象中:

// access modifiers omitted for brevity
class WhatIsYourNameActivity extends Activity { void onCreate(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(new Intent(this, GreetLoudlyActivity.class)); } }

  然后在第二个Activity中通过Application获取存储的用户信息:

// access modifiers omitted for brevity
class GreetLoudlyActivity extends Activity { TextView textview; void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.reading);
textview = (TextView) findViewById(R.id.message);
} void onResume() {
super.onResume(); MyApplication app = (MyApplication) getApplication();
textview.setText("HELLO " + app.getName().toUpperCase());
}
}

测试步骤

  1. 打开这个APP;

  2. 在WhatIsYourNameActivity中,你按要求输入用户名并将其缓存到MyApplication这个对象中;

  3. 接着在GreetLoudlyActivity中,程序从MyApplication对象中取出用户名并显示出来;

  4. 用户按了Home按键离开了该APP;

  5. 数小时之后,系统由于内存不足(用户在体验其它APP呢,前台的任务总是优先的嘛)会在后台将你的程序杀掉;在你重新启动该APP之前一切看上去很好,但是…..;

  6. 用户重新打开了这个APP;

  7. Android会重新创建一个之前被Kill掉的MyApplication实例并恢复GreetLoudlyActivity;

  8. GreetLoudlyActivity去获取用户名时,会因为获取的为空值报NullPointerException而崩溃掉。

为什么会这样?

  在上面这个例子中,程序之所以会崩溃掉是因为恢复之后APP的Application对象是全新的,所以缓存在Application中的用户 名成员变量为空值,在程序调用String的toUpperCase()方法时由于NullPointerException而崩溃掉。

  导致这个问题的主要原因是:Application对象并不是始终在内存中的,它有可能会由于系统内存不足而被杀掉。但Android在你恢复 这个应用时并不是重新开始启动这个应用,它会创建一个新的Application对象并且启动上次用户离开时的activity以造成这个app从来没有 被kill掉得假象。

  我们以为可以通过Application来缓存数据,却没想到恢复APP时直接跑了B Activity而不是先启动A Activity,最终导致的结果是程序意外的崩溃掉了。

有哪些替代方法可用呢?

  对于数据缓存问题我也没有比较好的办法,但你可以按照下面其中一种方式来处理:

  • 通过Intent在Activity之间来传递数据(但是请别传递大量数据,这有可能导致程序异常或者ANR);

  • 使用官方推荐的方法中的一种将数据持久化,存储在磁盘中;

  • 在使用数据和句柄的时候做空值检测;

不要在Android的Application对象中缓存数据!的更多相关文章

  1. 为什么不能往Android的Application对象里存储数据

    在一个App里面总有一些数据需要在多个地方用到.这些数据可能是一个 session token,一次费时计算的结果等.通常为了避免activity之间传递对象的开销 ,这些数据一般都会保存到持久化存储 ...

  2. 【安卓开发】为什么不能往Android的Application对象里存储数据

    在一个App里面总有一些数据需要在多个地方用到.这些数据可能是一个 session token,一次费时计算的结果等.通常为了避免activity之间传递对象的开销 ,这些数据一般都会保存到持久化存储 ...

  3. 不要在Application中缓存数据

    在你的App中的很多地方都需要使用到数据信息,它可能是一个session token,一次费时计算的结果等等,通常为了避免Activity之间传递数据的开销,会将这些数据通过持久化来存储.   有人建 ...

  4. Android 利用Application对象存取公共数据

    本文章来给大家介绍Android 利用Application对象存取公共数据. Android系统在运行每一个程序应用的时候,都会创建一个Application对象,用于存储与整个应用相关的公共变量. ...

  5. Application对象的使用-数据传递以及内存泄漏

    Application的使用 What is Application Application和Activity,Service一样是android框架的一个系统组件,当android程序启动时系统会创 ...

  6. .NET中利用反射来实现自动映射两个对象中的数据成员

    在以前的项目开发之中,经常会遇到这样一个问题:比如在外面项目的架构设计之中,我们采用MVC和EntityFramework来构建一个Web应用程序.比如我们采用常用的多层架构,例如有Presentat ...

  7. Android 向Application对象添加Activity监听

    可以建立对象把Application.ActivityLifecycleCallbacks接口中的函数实现,并利用public void registerActivityLifecycleCallba ...

  8. Android - 读取XML文件中的数据

    读取XML中存储的数据.将xmlfile.xml存放在assets文件夹中.在activity_main.xml中创建一个textview,用来显示读取到的数据. XML文件内容如下:xmlfile. ...

  9. angularJs中缓存数据,免去重复发起请求的几种写法

    带缓存处理的两种写法 过程:点击button触发load()方法,请求数据成后显示到页面中.如果已经请求过则从缓存中读取. 在线浏览 写法1: function demo(){ if (demo.ca ...

随机推荐

  1. 控制流之if

    if语句if语句用来检验一个条件, 如果 条件为真,我们运行一块语句(称为 if-块 ), 否则 我们处理另外一块语句(称为 else-块 ). else 从句是可选的. ~~~~~~~~~~~~~~ ...

  2. Laravel 数据插入

    Laravel 的数据库操作基于 Eloquent ORM,在插入数据时有以下几种方式,返回结果也不会不同: 1.insert 插入后会返回 true or false: 2.create 插入成功后 ...

  3. (中等) POJ 1703 Find them, Catch them,带权并查集。

    Description The police office in Tadu City decides to say ends to the chaos, as launch actions to ro ...

  4. Cookie的格式及组成

    转自:http://blog.csdn.net/talking12391239/article/details/9665185 Cookie由变量名和值组成,类似JavaScript变量.其属性里既有 ...

  5. Docker 命令(二)

    Docker 入门 启动docker systemctl start docker 帮助命令 docker --help docker [Commands] --help   例:docker run ...

  6. Python学习【第十二篇】模块(2)

    序列化 1.什么是python序列化? 把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling 序列化就是将python的数据类型转换成字符串 反序列化就是将字符串转换成 ...

  7. java实现——004替换空格

    1.创建新的字符串 public class T004 { public static void main(String[] args){ System.out.println(replaceBlan ...

  8. Zend Framework Module之多模块配置

    摘要:该文将为大家简单介绍一下如何使用zend framework创建模块化的应用程序. zend framework对多模块的支持是很好的,但是可能是由于功能太过强大的缘故,部署起来并不是很容易.许 ...

  9. UVa 459 - Graph Connectivity

    题目大意:给你一个无向图的顶点和边集,让你求图中连通分量的个数.使用并查集解决. #include <cstdio> #include <cstring> #define MA ...

  10. Beautifulsoup 和selenium 的查询

    Selenium There are vaious strategies to locate elements in a page. You can use the most appropriate ...