為何Android開發中不推薦使用全域變數傳參

來源:互聯網
上載者:User

Android開發中一般都是使用Intent給Activity傳參。有時需要傳複雜物件時,我們會傾向於用全域變數(靜態變數或Application屬性)。但其實這樣做是有隱患的,跟Activity的生命週期有關,正好最近遇到這個問題,在這裡寫一下。

大概情況是這樣的:ActivityA中點擊按鈕啟動ActivityB,同時要傳一個大資料對象,懶得對這個對象進行序列化,於是就直接搞了個全域變數ActivityB.param寫了進去,在ActivityB.onCreate裡讀取並顯示資訊,編譯運行一切正常。這樣過了大半個月似乎也沒發現什麼問題。直到有一天發給客戶使用後,在友盟後台看到了null 指標錯誤,仔細分析堆棧代碼,錯誤就在ActivityB.onCreate裡讀取全域變數時發生,也就是全域變數返回了空!

全域變數為空白一般就是由於記憶體不足進程被KILL過重新建立了。按常理分析,ActivityA在給ActivityB.param賦值後會立即啟動ActivityB,這過程很短,進程不可能這麼快被KILL,因此理論上ActivityB.onCreate中應該能讀取到ActivityB.param的。

實際上,在ActivityA給ActivityB.param賦值啟動ActivityB後,ActivityB.onCreate確實是能讀取到ActivityB.param的;但是,ActivityB並不能保證永遠在前台,一旦ActivityB所在任務被切到後台(如有電話打進來了),系統就可以在記憶體不足時將ActivityB所在的進程KILL掉;而當ActivityB所在任務被切回前台(如電話打完了),這時系統會自動重新恢複ActivityB,這時全域變數自然就沒了。

有人說我不用靜態變數,用Application的屬性來存全域參數,是不是就可以避免這個問題了呢?其實也是不行的,因為進程被KILL再恢複後,Application對象也是銷毀重建了的;安卓系統並不保證會在KILL進程前給程式發通知,因此我們也無法在Application裡儲存恢複全域變數。

另外,全域變數也不能記錄安卓的介面Context相關的類(如Activity、View),因為安卓系統自動管理這些類,記錄它們會導致引用計數增加無法釋放的記憶體泄露問題;如果一定要記錄,則應該使用弱引用WeakReference。

總之安卓開發中是不推薦用全域變數傳參的。最好的辦法還是按照安卓的開發規範,完全使用Intent進行傳參,因為系統在KILL進程前會自動儲存Activity堆棧,同時儲存相關的Intent參數,並自動進行恢複。如果非要用全域變數,則至少必須在讀取全域變數處理時判斷是否為空白,避免程式出錯崩潰;同時最好在onPause時自行儲存資料以便被KILL後恢複。

但是我覺得全域變數也不是一無是處完全不能用,主要是要理解並避開安卓進程生命週期中全域變數的變化。例如用全域變數來記錄自己寫的全域處理類(如工廠類、類註冊器等),只要注意在被進程KILL後做好恢複工作,是完全可以的。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.