精品伊人久久大香线蕉,开心久久婷婷综合中文字幕,杏田冲梨,人妻无码aⅴ不卡中文字幕

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
不要在Android的Application對象中緩存數據!

前言

在你的App中的很多地方都需要使用到數據信息,它可能是一個session token,一次費時計算的結果等等,通常為了避免Activity之間傳遞數據的開銷,會將這些數據通過持久化來存儲。

有人建議將這些數據放在Application對象中方便所有的Activity訪問,這個解決方案簡單、優雅并且是……完全錯誤的。

你如果你將數據緩存到Application對象中,那么有可能你的程序最終會由于一個NullPointerException異常而崩潰掉。

一個簡單的測試程序

這是自定義Application的代碼:

// access modifiers omitted for brevityclass MyApplication extends Application {     String name;     String getName() {        return name;    }     void setName(String name) {        this.name = name;    }}

在第一個Activity中,我們將用戶信息存儲在Application對象中:

// access modifiers omitted for brevityclass 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中通過Application獲取存儲的用戶信息:

// access modifiers omitted for brevityclass 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. 數小時之后,系統由于內存不足(用戶在體驗其它APP呢,前臺的任務總是優先的嘛)會在后臺將你的程序殺掉;在你重新啟動該APP之前一切看上去很好,但是…..;

  6. 用戶重新打開了這個APP;

  7. Android會重新創建一個之前被Kill掉的MyApplication實例并恢復GreetLoudlyActivity;

  8. GreetLoudlyActivity去獲取用戶名時,會因為獲取的為空值報NullPointerException而崩潰掉。

為什么會這樣?

在上面這個例子中,程序之所以會崩潰掉是因為恢復之后APP的Application對象是全新的,所以緩存在Application中的用戶名成員變量為空值,在程序調用String的toUpperCase()方法時由于NullPointerException而崩潰掉。

導致這個問題的主要原因是:Application對象并不是始終在內存中的,它有可能會由于系統內存不足而被殺掉。但Android在你恢復這個應用時并不是重新開始啟動這個應用,它會創建一個新的Application對象并且啟動上次用戶離開時的activity以造成這個app從來沒有被kill掉得假象。

我們以為可以通過Application來緩存數據,卻沒想到恢復APP時直接跑了B Activity而不是先啟動A Activity,最終導致的結果是程序意外的崩潰掉了。

有哪些替代方法可用呢?

對于數據緩存問題我也沒有比較好的辦法,但你可以按照下面其中一種方式來處理:

  • 通過Intent在Activity之間來傳遞數據(但是請別傳遞大量數據,這有可能導致程序異常或者ANR);

  • 使用官方推薦的方法中的一種將數據持久化,存儲在磁盤中;

  • 在使用數據和句柄的時候做空值檢測;

如何模擬應用程序被殺掉?

更新:Daniel Lew指出,最簡單的方法是在DDMS中點擊”Stop Porcess”殺掉你的程序,在你調試程序的時候可以這樣做。

你可以通過模擬器或者一個Root過的真機來測試實際效果:

  1. 按Home按鍵退出你的程序;

  2. 在控制臺,敲入如下命令(Windows系統下 WIN + R -> cmd -> 回車)

     # 找到該APP的進程ID adb shell ps # 找到你APP的報名	  # Mac/Unix: save some time by using grep: adb shell ps | grep your.app.package	  # 按照上述命令操作后,看起來是這樣子的:  # USER      PID   PPID  VSIZE  RSS     WCHAN    PC         NAME # u0_a198   21997 160   827940 22064 ffffffff 00000000 S your.app.package	  # 通過PID將你的APP殺掉 adb shell kill -9 21997	  # APP現在被殺掉啦
  3. 現在在桌面長按Home按鍵通過后臺任務管理器打開你的APP,此時系統就會重新創建一個MyApplication實例了。

總結

不要在Application對象中緩存數據化,這有可能會導致你的程序崩掉。請使用Intent在各組件之間傳遞數據,抑或是將數據存儲在磁盤中,然后在需要的時候取出來。

并不僅僅只有Application對象是這樣的,其它的單例或者公有靜態類也有可能會由于系統內存而被殺掉,謹記。



本站僅提供存儲服務,所有內容均由用戶發布,如發現有害或侵權內容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Android Application對象必須掌握的七點
使用ImageLoader實現圖片異步加載
[Android]異步加載圖片,內存緩存,文件緩存,imageview顯示圖片時增加淡入淡出動畫
[Android]騰訊Tinker熱修復框架簡單使用
安卓熱修復之AndFIX
Android開源日志庫Logger使用教程
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯系客服!

聯系客服

主站蜘蛛池模板: 静安区| 股票| 洪洞县| 庆城县| 临沧市| 海安县| 安义县| 卢氏县| 易门县| 乐山市| 清涧县| 甘肃省| 积石山| 张北县| 平谷区| 怀柔区| 乌苏市| 汉中市| 西乡县| 梓潼县| 错那县| 仪陇县| 九江市| 宁河县| 观塘区| 日土县| 沙洋县| 柘城县| 武平县| 建德市| 铁岭县| 黎城县| 拉萨市| 那曲县| 沭阳县| 南投市| 汉寿县| 门源| 平原县| 石林| 梁平县|