不要經過Application Object或者其餘全局靜態變量來存放數據

           不要經過Application Object或者其餘全局靜態變量來存放數據數據庫

 

    轉載請註明來自:http://blog.csdn.net/liaoqianchuan00/article/details/24399093app

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

 

概述

在咱們的應用程序中,不少地方可能用到同一個數據。不少時候咱們可能不想經過Intent在Activity之間傳遞或者持久化的存放這些數據來。spa

 

咱們可能會將這些數據存放在Application對象中,這樣咱們就能夠在全部的Activity中訪問了。這個方法很簡單,可是其實是徹底錯誤的。.net

 

你的程序可能會由於NullPointerException而crash掉,由於上面的方案是基於你假設你存放的數據一直都在那裏的。翻譯

 

例子

Application對象:對象

 

// access modifiers omitted for brevityblog

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 從新初始化.

相關文章
相關標籤/搜索