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

有人建议将这些数据保存到 Application 对象里面,这样这些数据对所有应用内的activities可用。这种方法简单,优雅而且……完全扯淡。

假设把你的数据都保存到Application对象里面去了,那么你的应用最后会以一个NullPointerException 异常crash掉。

一个简单的测试案例

代码

Application 对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
// access modifiers omitted for brevity
class MyApplication extends Application {
 
    String name;
 
    String getName() {
        return name;
    }
 
    void setName(String name) {
        this.name = name;
    }
}

第一个activity,我们往application对象里面存储了用户姓名:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 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,我们调用第一个activity设置并存在application里面的用户姓名:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 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. 几个小时后,Android系统为了回收内存kill掉了这个app。到目前为止,一切尚好。接下来就是crash的部分了…
  6. 用户重新打开这个App。
  7. Android系统创建一个新的 MyApplication 实例并恢复 GreetLoudlyActivity。
  8. GreetLoudlyActivity 从新的 MyApplication 实例中获取用户姓名,可得到的为空,最后导致NullPointerException。

为什么会Crash?

在上面这个例子中,app会crash得原因是这个 Application 对象是全新的,所以这个name 变量里面的值为 null,当调用String#toUpperCase() 方法时就导致了NullPointerException。

整个问题的核心在于:application 对象不会一直呆着内存里面,它会被kill掉。与大家普遍的看法不同之处在于,实际上app不会重新开始启动。Android系统会创建一个新的Application 对象,然后启动上次用户离开时的activity以造成这个app从来没有被kill掉得假象。

你以为你的application可以保存数据,却没想到你的用户在没有打开activity A 之前就就直接打开了 activity B ,于是你就收到了一个 crash 的 surprise。

有哪些替代方法呢?

这里没啥神奇的解决方法,你可以试试下面几种方法:

  • 直接将数据通过intent传递给 Activity 。
  • 使用官方推荐的几种方式将数据持久化到磁盘上。
  • 在使用数据的时候总是要对变量的值进行非空检查。

如果模拟App被Kill掉

更新: Daniel Lew指出,kill app更简单的方式就是使用DDMS里面“停止进程” 。你在调试你的应用的时候可以使用这招。

为了测试这个,你必须使用一个Android模拟器或者一台root过的Android手机。

  1. 使用home按钮退出app。
  2. 在终端里:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # 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. 长按home按钮回到之前的app。
    你现在是出于一个新的application实例中了。

总结

不要在application对象里面储存数据,这容易出错,导致你的app crash。
要么将你后面要用的数据保存到磁盘上面或者保存到intent得extra里面直接传递给activity 。

这些结论不但对application对象有用,对你app里面的单例对象(singleton)或者公共静态变量(public static)同样适用。

【安卓开发】为什么不能往Android的Application对象里存储数据的更多相关文章

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

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

  2. 不要在Android的Application对象中缓存数据!

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

  3. 安卓开发_浅谈Android动画(四)

    Property动画 概念:属性动画,即通过改变对象属性的动画. 特点:属性动画真正改变了一个UI控件,包括其事件触发焦点的位置 一.重要的动画类及属性值: 1.  ValueAnimator 基本属 ...

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

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

  5. 安卓开发第一步:Android Studio安装配置

    虽然本人是JAVA开发工程师平时主要开发Web App,但因为项目需求需要开发对应的移动端.一时又找不到合适的安卓开发人员,兄弟我只好被项目经理"抓来当壮丁了".俗话说好" ...

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

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

  7. 【Bugly安卓开发干货分享】Android APP 快速 Pad 化实现

    项目背景 采用最新版本手机 APP(之后称为 MyApp)代码,实现其 Pad 化,为平板和大屏手机用户提供更好的体验.为实现 MyApp 的 Pad 化工作,需要我们首先来了解一下 MyApp 项目 ...

  8. 重拾安卓_01_安卓开发环境搭建(android studio)

    一.下载安装SDK 参考:搭建Android开发环境——Eclipse  的安装SDK部分 二.安装android studio 参考: Android Studio 入门级教程(一) 三.andro ...

  9. 安卓开发学习日记 DAY2——android项目文件

    当一个android项目建立时,会有一个目录,以下为目录所包含内容 src:放置java源代码 gen:基本不会做任何更改,放置自动生成的配置文件(主要是R文件) Android4.4.2:放置当前版 ...

随机推荐

  1. [LeetCode] Solve the Equation 解方程

    Solve a given equation and return the value of x in the form of string "x=#value". The equ ...

  2. 【Swift】swift定义全局变量

    swift定义全局变量非常简单哈,只要在类class上面直接定义,就是全局变量了 当需要在类里面定义一个类函数访问的变量的时候,直接在var或者let 前面加一个 static

  3. cd

    从当前目录切换到目标目录 cd [目标目录]   切换到用户主目录 cd cd~   切换到根目录 cd /   切换到上级目录 cd .. cd ../ cd ..//   切换到上级目录的父目录 ...

  4. Java IO(三)

    在Java IO提供的类中,除了前面介绍的RandomAccessFile类之外,还有一系列的io操作类. 主要分为两大类.字符流和字节流.关系图如下: 在Java IO的操作中,很好的体现了Java ...

  5. [HNOI 2016]大数

    Description 题库链接 给你一个长度为 \(n\) ,可含前导零的大数,以及一个质数 \(p\) . \(m\) 次询问,每次询问你一个大数的子区间 \([l,r]\) ,求出子区间中有多少 ...

  6. [HNOI 2008]越狱

    Description 监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种.如果 相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱 I ...

  7. [JLOI 2012]树

    Description 在这个问题中,给定一个值S和一棵树.在树的每个节点有一个正整数,问有多少条路径的节点总和达到S.路径中节点的深度必须是升序的.假设节点1是根节点,根的深度是0,它的儿子节点的深 ...

  8. [SHOI2008]汉诺塔

    Description 汉诺塔由三根柱子(分别用A B C表示)和n个大小互不相同的空心盘子组成.一开始n个盘子都摞在柱子A上, 大的在下面,小的在上面,形成了一个塔状的锥形体. 对汉诺塔的一次合法的 ...

  9. [HNOI2004]树的计数

    题目描述 输入输出格式 输入格式: 输入文件第一行是一个正整数n,表示树有n个结点.第二行有n个数,第i个数表示di,即树的第i个结点的度数.其中1<=n<=150,输入数据保证满足条件的 ...

  10. [bzoj4828][Ah/Hnoi2017]大佬

    来自FallDream的博客,未经允许,请勿转载,谢谢. 人们总是难免会碰到大佬.他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢言语. 你 ...