文档章节

不要通过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
粉丝 122
博文 477
码字总数 138530
作品 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

没有更多内容

加载失败,请刷新页面

加载更多

下一页

基于TP5的微信的公众号获取登录用户信息

之前讲过微信的公众号自动登录的菜单配置,这次记录一下在TP5项目中获取自动登录的用户信息并存到数据库的操作 基本的流程为:微信设置自动登录的菜单—>访问的URL指定的函数里获取用户信息—...

月夜中徘徊
56分钟前
0
0
youTrack

package jetbrains.teamsys.license.runtime; 计算lis package jetbrains.ring.license.reader; 验证lis 安装后先不要生成lis,要把相关文件进行替换 ring-license-checker-1.0.41.jar char......

max佩恩
59分钟前
0
0
12.17 Nginx负载均衡

Nginx负载均衡 下面的dig看到可以返回2个IP,就是解析出来的IP,这样我们可以做负载均衡。 dig www.qq.com 1.vim /usr/local/nginx/conf/vhost/fuzai.conf 2.添加如下配置 upstream qq //定义...

芬野de博客
今天
0
0
SSE(Server Send Event 服务端发送事件)

package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframe......

Canaan_
今天
0
0
jvm调优

1.jvm运行模式 client模式:启动快,占用内存少,jit编译器生成代码的速度也更快. server模式:主要优势在于代码优化功能,这个功能对于服务器应用而言尤其重要. tiered server模式:结合了client与...

Funcy1122
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部