-
介紹:
Application
是單例模式的類柏腻,android
系統(tǒng)為每個(gè)應(yīng)用程序創(chuàng)建一個(gè)Application
類的對(duì)象且只創(chuàng)建一個(gè)泉粉。
啟動(dòng)Application
時(shí),系統(tǒng)會(huì)創(chuàng)建一個(gè)PID灵莲,即進(jìn)程ID路克,所有的Activity
都會(huì)在此進(jìn)程上運(yùn)行。
Application
創(chuàng)建的時(shí)候初始化全局變量琼开,同一個(gè)應(yīng)用的所有Activity
都可以取到這些全局變量的值
Application
對(duì)象的生命周期是整個(gè)程序中最長(zhǎng)的易结,它的生命周期就等于這個(gè)程序的生命周期
Application
全局的單例的,所以在不同的Activity,Service
中獲得的對(duì)象都是同一個(gè)對(duì)象
-
應(yīng)用領(lǐng)域:數(shù)據(jù)傳遞柜候、數(shù)據(jù)共享和數(shù)據(jù)緩存等操作搞动。
- 復(fù)雜數(shù)據(jù)的傳遞:
-
Activity A,
跳轉(zhuǎn)到Activity B
,用Intent.putExtra()
或者Bundle
進(jìn)行傳遞數(shù)據(jù)渣刷,但是:Intent和Bundle
所能攜帶的數(shù)據(jù)類型都是一些基本的數(shù)據(jù)類型鹦肿,想實(shí)現(xiàn)復(fù)雜的數(shù)據(jù)傳遞就比較麻煩了,通常需要實(shí)現(xiàn)Serializable
或者Parcellable接口
- 用
Application
進(jìn)行解決:(思路)
在Application
中創(chuàng)建一個(gè)HashMap
辅柴,以字符串為索引箩溃,Object
為value這樣我們的HashMap
就可以存儲(chǔ)任何類型的對(duì)象了。在Activity A
中把需要傳遞的對(duì)象放入這個(gè)HashMap
碌嘀,然后通過(guò)Intent
或者其它途經(jīng)再把這索引的字符串傳遞給Activity B
,Activity B
就可以根據(jù)這個(gè)字符串在HashMap
中取出這個(gè)對(duì)象了涣旨。只要再向下轉(zhuǎn)個(gè)型 ,就實(shí)現(xiàn)了對(duì)象的傳遞股冗。
-
- 復(fù)雜數(shù)據(jù)的傳遞:
-
生命周期
-
onCreate
在創(chuàng)建應(yīng)用程序時(shí)創(chuàng)建 -
onTerminate
當(dāng)終止應(yīng)用程序?qū)ο髸r(shí)調(diào)用霹陡,不保證一定被調(diào)用,當(dāng)程序是被內(nèi)核終止以便為其他應(yīng)用程序釋放資源魁瞪,那么將不會(huì)提醒穆律,并且不調(diào)用應(yīng)用程序的對(duì)象的onTerminate
方法而直接終止進(jìn) 程 -
onLowMemory
當(dāng)后臺(tái)程序已經(jīng)終止資源還匱乏時(shí)會(huì)調(diào)用這個(gè)方法。好的應(yīng)用程序一般會(huì)在這個(gè)方法里面釋放一些不必要的資源來(lái)應(yīng)付當(dāng)后臺(tái)程序已經(jīng)終止导俘,前臺(tái)應(yīng)用程序內(nèi)存還不夠時(shí)的情況峦耘。onConfigurationChanged
配置改變時(shí)觸發(fā)這個(gè)方法 -
備注:
application 被殺死的情況分析
:(Application
的生命周期代表這個(gè)應(yīng)用的生命周期)
為了決定在內(nèi)存較低的時(shí)候殺掉哪個(gè)進(jìn)程, Android會(huì)根據(jù)運(yùn)行在這些進(jìn)程內(nèi)的組件及他們的狀態(tài)把進(jìn)程劃分成一個(gè)”重要程度層次”. 其重要的程度按以下規(guī)則排序:- 1:前端進(jìn)程可以是一個(gè)持有運(yùn)行在屏幕最前端并與用戶交互的Activity的進(jìn)程(onResume方法被調(diào)用時(shí)),也可以是持有一個(gè)正在運(yùn)行的IntentReceiver(也就是說(shuō)他正在執(zhí)行自己的onReceiveIntent方法)的進(jìn)程. 在系統(tǒng)中, 只會(huì)有少數(shù)這樣的進(jìn)程, 并且除非內(nèi)存已經(jīng)低到不夠這些進(jìn)程運(yùn)行, 否則系統(tǒng)不會(huì)主動(dòng)殺掉這些進(jìn)程. 這時(shí), 設(shè)備通常已經(jīng)達(dá)到了需要內(nèi)存整理的狀態(tài), 所以殺掉這些進(jìn)程是為了不讓用戶界面停止響應(yīng).
- 2:可視進(jìn)程是持有一個(gè)被用戶可見(jiàn), 但沒(méi)有顯示在最前端 (onPause方法被調(diào)用時(shí)) 的Activity的進(jìn)程. 舉例來(lái)說(shuō), 這種進(jìn)程通常出現(xiàn)在一個(gè)前端Activity以一個(gè)對(duì)話框出現(xiàn)并保持前一個(gè)Activity可見(jiàn)時(shí). 這種進(jìn)程被系統(tǒng)認(rèn)為是極其重要的, 并且通常不會(huì)被殺掉, 除非為了保持所有前端進(jìn)程正常運(yùn)行不得不殺掉這些可見(jiàn)進(jìn)程.
- 3:服務(wù)進(jìn)程是持有一個(gè)Service的進(jìn)程, 該Service是由startService()方法啟動(dòng)的, 盡管這些進(jìn)程用戶不能直接看到, 但是通常他們做的工作用戶是十分關(guān)注的(例如, 在后臺(tái)播放mp3或是在后臺(tái)下載 上傳文件), 所以, 除非為了保持所有的前端進(jìn)程和可視進(jìn)程正常運(yùn)行外, 系統(tǒng)是不會(huì)殺掉服務(wù)進(jìn)程的.
- 4:后臺(tái)進(jìn)程是持有一個(gè)不再被用戶可見(jiàn)的Activity(onStop()方法被調(diào)用時(shí))的進(jìn)程. 這些進(jìn)程不會(huì)直接影響用戶體驗(yàn). 加入這些進(jìn)程已經(jīng)完整的,正確的完成了自己的生命周期(訪問(wèn)Activity查看更多細(xì)節(jié)), 系統(tǒng)會(huì)在為前三種進(jìn)程釋放內(nèi)存時(shí)隨時(shí)殺掉這些后臺(tái)進(jìn)程. 通常會(huì)有很多的后臺(tái)進(jìn)程在運(yùn)行, 所以這些進(jìn)程被存放在一個(gè)LRU列表中, 以保證在低內(nèi)存的時(shí)候, 最近一個(gè)被用戶看到的進(jìn)程會(huì)被最后殺掉.
- 5:空進(jìn)程是沒(méi)有持有任何活動(dòng)應(yīng)用組件的進(jìn)程. 保留這種進(jìn)程的唯一理由是為了提供一種緩存機(jī)制, 縮短他的應(yīng)用下次運(yùn)行時(shí)的啟動(dòng)時(shí)間. 就其本身而言, 系統(tǒng)殺掉這些進(jìn)程的目的是為了在這些空進(jìn)程和底層的核心緩存之間平衡整個(gè)系統(tǒng)的資源. 來(lái)自:
www.2cto.com
- 當(dāng)需要給一個(gè)進(jìn)程分類的時(shí)候, 系統(tǒng)會(huì)在該進(jìn)程中處于活動(dòng)狀態(tài)的所有組件里掉選一個(gè)重要等級(jí)最高作為分類依據(jù). 查看Activity, Service,和IntentReceiver的文檔, 了解每個(gè)組件在進(jìn)程整個(gè)生命周期中的貢獻(xiàn). 每一個(gè)classes的文檔詳細(xì)描述他們?cè)?strong>各自應(yīng)用的生命周期中所起得作用.
-
實(shí)現(xiàn)步驟:
1.繼承Application
public class CustomApplication extends Application{
@Override
public void onCreate(){}
}
繼承Application類
旅薄,主要重寫里面的onCreate()
方法(android.app.Application包的onCreate()才是真正的Android程序的入口點(diǎn))
2.在AndroidManifest.xml
文件中配置自定義的Application
<application
android:name="CustomApplication">
</application>
-
如何獲得
Application
的信息(全局變量)呢辅髓?public class FirstActivity extends Activity{ private CustomApplication app; @Override public void onCreate(Bundle savedInstanceState){ ..... app = (CustomApplication) getApplication(); // 獲得CustomApplication對(duì)象 Log.i("FirstActivity", "初始值=====" + app.getValue()); // 獲取進(jìn)程中的全局變量值泣崩,看是否是初始化值 app.setValue("Harvey Ren"); // 重新設(shè)置值 Log.i("FirstActivity", "修改后=====" + app.getValue()); // 再次獲取進(jìn)程中的全局變量值,看是否被修改 } }
只需要調(diào)用Context
的 getApplicationContext
或者Activity的getApplication方法
來(lái)獲得一個(gè)Application對(duì)象洛口,然后再得到相應(yīng)的成員變量即可矫付。
-
知識(shí)延伸:
MemoryLeak
在Java中內(nèi)存泄漏是指:某個(gè)(某些)對(duì)象已經(jīng)不在被使用應(yīng)該被gc所回收,但有一個(gè)對(duì)象持有這個(gè)對(duì)象的引用而阻止這個(gè)對(duì)象被回收第焰。比如我們通常會(huì)這樣創(chuàng)建一個(gè)View TextView tv = new TextView(this);
這里的this
通常都是Activity
买优。所以這個(gè)TextView
就持有著這個(gè)Activity的引用。
通常情況下挺举,當(dāng)用戶轉(zhuǎn)動(dòng)手機(jī)的時(shí)候杀赢,android會(huì)重新調(diào)用OnCreate()
方法生成一個(gè)新的Activity,原來(lái)的 Activity應(yīng)該被GC所回收湘纵。但如果有個(gè)對(duì)象比如一個(gè)View的作用域超過(guò)了這個(gè)Activity(比如有一個(gè)static
對(duì)象或者我們把這個(gè) View
的引用放到了Application
當(dāng)中)脂崔,這時(shí)候原來(lái)的Activity將不能被GC所回收,Activity
本身又持有很多對(duì)象的引用梧喷,所以 整個(gè)Activity的內(nèi)存被泄漏了砌左。
備注:經(jīng)常導(dǎo)致內(nèi)存泄漏核心原因:
keeping a long-lived reference to a Context.持有一個(gè)context的對(duì)象,從而gc不能回收铺敌。
- 1.**一個(gè)View的作用域超出了所在的Activity的作用域**汇歹,比如一個(gè)static的View或者把一個(gè)View cache到了application當(dāng)中 etc
理解:內(nèi)存:注意靜態(tài)的數(shù)據(jù)和緩存中的數(shù)據(jù);注意釋放适刀;
- 2.某些與View關(guān)聯(lián)的Drawable的作用域超出了Activity的作用域秤朗。
- 3.Runnable對(duì)象:比如在一個(gè)Activity中啟用了一個(gè)新線程去執(zhí)行一個(gè)任務(wù),在這期間這個(gè)Activity被系統(tǒng)回收了笔喉, 但Runnalbe的 任務(wù)還沒(méi)有執(zhí)行完畢并持有Activity的引用而泄漏,但這種泄漏一般來(lái)泄漏一段時(shí)間硝皂,只有Runnalbe的線程執(zhí)行完閉常挚,這個(gè) Activity又可以被正常回收了稽物。
- 4.內(nèi)存類的對(duì)象作用域超出Activity的范圍:比如定義了一個(gè)內(nèi)存類來(lái)存儲(chǔ)數(shù)據(jù)奄毡,又把這個(gè)內(nèi)存類的對(duì)象傳給了其它Activity 或者Service等。因?yàn)閮?nèi)部類的對(duì)象會(huì)持有當(dāng)前類的引用贝或,所以也就持有了Context的引用吼过。解決方法
是如果不需要當(dāng)前的引用把內(nèi)部類寫成static或者,把內(nèi)部類抽取出來(lái)變成一個(gè)單獨(dú)的類咪奖,或者把避免內(nèi)部對(duì)象作用域超出Activity的作用域盗忱。
out Of Memery Error
在android中每一個(gè)程序所分到的內(nèi)存大小是有限的,如果超過(guò)了這個(gè)數(shù)就會(huì)報(bào)Out Of Memory Error
羊赵。
- 注意:所以盡量把程序中的一些大的數(shù)據(jù)cache到本地文件趟佃。以免內(nèi)存使用量超標(biāo)。記得數(shù)據(jù)傳遞完成之后,把存放在application的HashMap中的數(shù)據(jù)remove掉
闲昭,以免發(fā)生內(nèi)存的泄漏罐寨。
-
參考資料:
Android中Application類用法
android application 詳解--深入淺出,講解完整的Application序矩,以及所涉及到的擴(kuò)展知識(shí)鸯绿。
Android筆記 Application對(duì)象的使用-數(shù)據(jù)傳遞以及內(nèi)存泄漏問(wèn)題