Application对象中存储的数据一直存在?

勿存数据于Application
本文警告开发者不要将数据存储在Android的Application对象中,因为这可能导致应用因NullPointerException异常而崩溃。文章通过一个示例展示了当用户离开并重新进入应用时,新的Application实例会导致之前存储的数据丢失,进而引发异常。


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


千万不要把数据存储在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对象来说是这种情况,那么对于任何单例对象或者静态属性来说都如此

注:经过自己的测试,确实出现如作者所描述的情况










<think>好的,我现在需要解决用户的问题:JSP中的application对象的类型是ServletContext吗?让我仔细分析一下。 首先,用户提供的引用资料中有多个来源提到了application和ServletContext的关系。比如引用[2]明确说ServletContext和application是同一个对象,只是名称不同。引用[3]也提到在JSP中全局变量称为application,而在Servlet中则叫ServletContext。此外,引用[5]说明application对象是应用程序级的,生命周期与服务器一致,这与ServletContext的特性一致。 然后,我需要确认JSP中的内置对象application是否确实是ServletContext类型。根据引用[2],JSP编译后的Servlet代码中有这样的声明:ServletContext application = pageContext.getServletContext(); 这直接证明了application对象是ServletContext类型的实例。 不过,用户可能还关心两者的区别。比如引用[2]提到,虽然本质相同,但在不同上下文中的使用方式可能有差异。例如,在JSP页面中可以直接使用application作为隐式对象,而在Servlet中需要通过getServletContext()方法获取。 总结来说,用户的问题核心在于确认类型,而根据提供的资料,答案应该是肯定的。同时,需要解释两者的关系以及在不同环境下的使用方式,确保回答全面准确。</think>### JSP中application对象的类型解析 在JSP中,`application`对象的类型为`javax.servlet.ServletContext`。以下是详细说明: #### 1. **对象类型与本质** - **类型声明**:`application`是JSP的内置对象,其实际类型为`ServletContext`。从JSP编译后的Servlet代码中可以看到以下声明: ```java ServletContext application = null; application = pageContext.getServletContext(); ``` 这表明`application`是`ServletContext`的实例[^2][^3]。 - **单例性质**:`ServletContext`是Web应用程序全局唯一的对象,与`application`指向同一实例。两者的区别仅在于名称和访问上下文的不同[^2][^5]。 #### 2. **作用与功能** `application`(即`ServletContext`)的核心功能包括: - **共享全局数据**:所有客户端和Servlet均可访问存储在其中的属性。 - **获取初始化参数**:通过`web.xml`中定义的`<context-param>`读取全局配置。 - **资源路径映射**:通过`getRealPath()`等方法获取服务器文件的物理路径[^4]。 #### 3. **与其他作用域对象的对比** | 对象 | 作用域 | 类型 | 生命周期 | |-------------|----------------|--------------------|------------------------| | `request` | 单次HTTP请求 | `HttpServletRequest` | 请求开始到响应结束 | | `session` | 用户会话 | `HttpSession` | 会话创建到超时或失效 | | `application` | 整个Web应用 | `ServletContext` | 服务器启动到关闭 | #### 4. **在JSP与Servlet中的使用差异** - **JSP中**:直接使用隐式对象`application`,例如: ```jsp <% application.setAttribute("key", "value"); %> ``` - **Servlet中**:需通过`getServletContext()`方法获取: ```java ServletContext context = getServletContext(); context.setAttribute("key", "value"); ``` #### 5. **EL表达式中的访问** 在EL(Expression Language)中,需通过`applicationScope`访问`application`作用域下的属性: ```jsp ${applicationScope.key} ``` ### 总结 `application`对象是JSP对`ServletContext`的封装,两者本质相同,但使用场景略有差异。其核心作用是为整个Web应用提供全局数据共享和资源配置能力[^2][^4]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值