文档章节

不要通过Application Object或者其他全局静态变量来存放数据

SuShine
 SuShine
发布于 2015/06/23 09:24
字数 947
阅读 38
收藏 0

           不要通过Application Object或者其他全局静态变量来存放数据

 

    转载请注明来自:http://blog.csdn.net/liaoqianchuan00/article/details/24399093

翻译自:http://www.developerphil.com/dont-store-data-in-the-application-object/

 

概述

在我们的应用程序中,很多地方可能用到同一个数据。很多时候我们可能不想通过Intent在Activity之间传递或者持久化的存放这些数据来。

 

我们可能会将这些数据存放在Application对象中,这样我们就可以在所有的Activity中访问了。这个方法很简单,但是实际上是完全错误的。

 

你的程序可能会因为NullPointerException而crash掉,因为上面的方案是基于你假设你存放的数据一直都在那里的。

 

例子

Application对象:

 

// access modifiers omitted for brevity

class MyApplication extends Application {

 

    String name;

 

    String getName() {

        returnname;

    }

 

    void setName(String name) {

        this.name= name;

    }

}

 

在第一个Activity中,我们将一个用户的名字存放在Application中:

 

// access modifiers omitted for brevity

class WhatIsYourNameActivity extends Activity {

 

    void onCreate(BundlesavedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.writing);

 

        //Just assume that in the real app we would really ask it!

        MyApplicationapp = (MyApplication) getApplication();

        app.setName("DeveloperPhil");

        startActivity(newIntent(this, GreetLoudlyActivity.class));

 

    }

 

}

 

在第二个Activity中,我们取出这个用户的名字:

 

// access modifiers omitted for brevity

class GreetLoudlyActivity extends Activity {

 

    TextView textview;

 

    void onCreate(BundlesavedInstanceState) {

        super.onCreate(savedInstanceState);

 

        setContentView(R.layout.reading);

        textview= (TextView) findViewById(R.id.message);

    }

 

    void onResume() {

        super.onResume();

 

        MyApplicationapp = (MyApplication) getApplication();

        textview.setText("HELLO" + app.getName().toUpperCase());

    }

}

 

场景

1.       用户打开程序。

2.       在WhatIsYourNameActivity中,你询问用户的名字,并且把它存放到Application中。

3.       在GreetLoudlyActivity中,你从MyApplication对象中取出用户的名字并且显示。

4.       用户按Home键离开我们的应用程序。

5.       数小时后,Android系统可能杀掉你的程序来获得更多的内存。

到现在为止,看起来都很正常。但是Crash马上就要发生了。

6.       用户重新打开程序。

7.       Android建立一个新的MyApplication实例,并且重新恢复GreetLoudlyActivity。

8.       GreetLoudlyActivity取得用户的名字,但是现在已经是null了,然后报错NullPointerException。

 

为什么会Crash?

在这个例子中,因为Application实例是重新创建的,所以name变量是null,导致我们在调用String->toUpperCase的时候报NullPointerException。

 

这就将我们引向了核心问题:Application对象不会一直在内存中存在,他可能被杀掉。和我们认为的相反,他不会恢复以前的信息。Android会创建一个新的Application对象,然后重新打开之前用户按Home离开的那个Activity。

 

这就是说,如果你假设Activity B不可能在Activity A之前开启,所以你保存数据在Application中,那么你的程序可能就会crash。

 

解决方案

1.       通过Intent在Activity之间传递数据。

2.       使用多种持久化保存数据的方式(文件,数据库,sharedpreference等)。

3.       做null判断,并且手动处理null的情况。

 

如何模拟应用程序被杀掉

1.       按Home键离开你的应用程序

2.       打开DDMS,选中你应用程序的进程,点击“stop process”。

3.       使用task switcher返回你的应用程序。现在你的应用程序的Application对象就是一个新的实例了。

 

总结

在Application对象中保存数据室错误的并且可能导致你的程序crash,使用Intent来传递数据或者将数据保存在disk上。

 

同时记住,这个问题同样适用于任何单例或者公共的静态变量。

 

 

备注:  在实际项目中却还是使用到了单例和静态变量, 所以可能导致后台很长时间之后崩溃, 现在的解决方案是

保存在Activity的成员变量 应该用 onsave存起来 单例 应该在i()中进行一次初始化

或者在 oncreate 重新初始化.

 

 

本文转载自:http://blog.csdn.net/liaoqianchuan00/article/details/24399093

共有 人打赏支持
SuShine
粉丝 123
博文 504
码字总数 148768
作品 0
朝阳
后端工程师
C可执行文件的内存结构

以前看过C可执行文件的内存结构,但都只是当时很清楚,时候就忘的差不多了,没有细细去品味,一段时间就忘得差不多了,今天看了一些书籍和博文,决定将C可执行文件的内存结构的内容通过博客记...

Jeff_Linux
2014/07/19
0
0
一种Android应用内全局获取Context实例的装置

哥白尼·罗斯福·马丁路德·李开复·嫁衣曾经说过 Where there is an Android App, there is an Application context. 没毛病,扎心了。App运行的时候,肯定是存在至少一个Application实例的...

Kaede
2017/04/10
0
0
Linux下C程序进程地址空间布局

我们在学习C程序开发时经常会遇到一些概念:代码段、数据段、BSS段(Block Started by Symbol) 、堆(heap)和栈(stack)。先看一张教材上的示意图(来源,《UNIX环境高级编程》一书),显...

zhangyujsj
2014/04/11
0
0
C语言局部变量和全局变量问题汇总

1、局部变量能否和全局变量重名? 答:能,局部会屏蔽全局。要用全局变量,需要使用"::" 局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。...

graylee
2013/10/28
0
0
文件输入输出中遇到的大端序和小端序问题

目录 include /** 联合类型的变量类型,用于测试字节序 成员value的高低端字节可以由成员byte按字节访问 * */ typedef union{ }to; int main(int argc, char *argv[]){ } int j=1;cout<<&i<......

dukeke
2015/09/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

MySQL面试题集锦

什么是数据库索引?索引有哪几种类型?什么是最左前缀原则?索引算法有哪些?有什么区别? 索引是对数据库表中一列或多列的值进行排序的一种结构。一个非常恰当的比喻就是书的目录页与书的正...

老道士
17分钟前
0
0
使用 LogStash 归集日志

elastic 官网: https://www.elastic.co/ 为了便于集中查看多台主机的业务日志,使用 Filebeat, Redis, Logstash的方式进行收集: (1) Filebeat 监控日志文件的变化, 将新增部分写入redis中, 每...

ouhoo
20分钟前
0
0
java序列化(六) - protostuff序列化

添加依赖 <dependency> <groupId>io.protostuff</groupId> <artifactId>protostuff-core</artifactId> <version>1.5.9</version> </de......

晨猫
26分钟前
0
0
Ceph学习笔记1-Mimic版本多节点部署

特别说明: 本方法也可以用于单节点部署,只部署一个Monitor(只是会形成单点故障而已),最低要求是使用两个分区创建2个OSD(因为默认最小副本是2);如果不需要使用CephFS,则可以不部署M...

LastRitter
29分钟前
0
0
923. 3Sum With Multiplicity - LeetCode

Question 923. 3Sum With Multiplicity Solution 题目大意: 给一个int数组A和一个目标值target,求满足下面两个条件的组合个数,其中i,j,k分别为数组的索引 i<j<k target = A[i] + A[j] + A[k...

yysue
30分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部