-
介紹:
Application
是單例模式的類,android
系統為每個應用程序創建一個Application
類的對象且只創建一個。
啟動Application
時,系統會創建一個PID,即進程ID,所有的Activity
都會在此進程上運行。
Application
創建的時候初始化全局變量,同一個應用的所有Activity
都可以取到這些全局變量的值
Application
對象的生命周期是整個程序中最長的,它的生命周期就等于這個程序的生命周期
Application
全局的單例的,所以在不同的Activity,Service
中獲得的對象都是同一個對象
-
應用領域:數據傳遞、數據共享和數據緩存等操作。
- 復雜數據的傳遞:
-
Activity A,
跳轉到Activity B
,用Intent.putExtra()
或者Bundle
進行傳遞數據,但是:Intent和Bundle
所能攜帶的數據類型都是一些基本的數據類型,想實現復雜的數據傳遞就比較麻煩了,通常需要實現Serializable
或者Parcellable接口
- 用
Application
進行解決:(思路)
在Application
中創建一個HashMap
,以字符串為索引,Object
為value這樣我們的HashMap
就可以存儲任何類型的對象了。在Activity A
中把需要傳遞的對象放入這個HashMap
,然后通過Intent
或者其它途經再把這索引的字符串傳遞給Activity B
,Activity B
就可以根據這個字符串在HashMap
中取出這個對象了。只要再向下轉個型 ,就實現了對象的傳遞。
-
- 復雜數據的傳遞:
-
生命周期
-
onCreate
在創建應用程序時創建 -
onTerminate
當終止應用程序對象時調用,不保證一定被調用,當程序是被內核終止以便為其他應用程序釋放資源,那么將不會提醒,并且不調用應用程序的對象的onTerminate
方法而直接終止進 程 -
onLowMemory
當后臺程序已經終止資源還匱乏時會調用這個方法。好的應用程序一般會在這個方法里面釋放一些不必要的資源來應付當后臺程序已經終止,前臺應用程序內存還不夠時的情況。onConfigurationChanged
配置改變時觸發這個方法 -
備注:
application 被殺死的情況分析
:(Application
的生命周期代表這個應用的生命周期)
為了決定在內存較低的時候殺掉哪個進程, Android會根據運行在這些進程內的組件及他們的狀態把進程劃分成一個”重要程度層次”. 其重要的程度按以下規則排序:- 1:前端進程可以是一個持有運行在屏幕最前端并與用戶交互的Activity的進程(onResume方法被調用時),也可以是持有一個正在運行的IntentReceiver(也就是說他正在執行自己的onReceiveIntent方法)的進程. 在系統中, 只會有少數這樣的進程, 并且除非內存已經低到不夠這些進程運行, 否則系統不會主動殺掉這些進程. 這時, 設備通常已經達到了需要內存整理的狀態, 所以殺掉這些進程是為了不讓用戶界面停止響應.
- 2:可視進程是持有一個被用戶可見, 但沒有顯示在最前端 (onPause方法被調用時) 的Activity的進程. 舉例來說, 這種進程通常出現在一個前端Activity以一個對話框出現并保持前一個Activity可見時. 這種進程被系統認為是極其重要的, 并且通常不會被殺掉, 除非為了保持所有前端進程正常運行不得不殺掉這些可見進程.
- 3:服務進程是持有一個Service的進程, 該Service是由startService()方法啟動的, 盡管這些進程用戶不能直接看到, 但是通常他們做的工作用戶是十分關注的(例如, 在后臺播放mp3或是在后臺下載 上傳文件), 所以, 除非為了保持所有的前端進程和可視進程正常運行外, 系統是不會殺掉服務進程的.
- 4:后臺進程是持有一個不再被用戶可見的Activity(onStop()方法被調用時)的進程. 這些進程不會直接影響用戶體驗. 加入這些進程已經完整的,正確的完成了自己的生命周期(訪問Activity查看更多細節), 系統會在為前三種進程釋放內存時隨時殺掉這些后臺進程. 通常會有很多的后臺進程在運行, 所以這些進程被存放在一個LRU列表中, 以保證在低內存的時候, 最近一個被用戶看到的進程會被最后殺掉.
- 5:空進程是沒有持有任何活動應用組件的進程. 保留這種進程的唯一理由是為了提供一種緩存機制, 縮短他的應用下次運行時的啟動時間. 就其本身而言, 系統殺掉這些進程的目的是為了在這些空進程和底層的核心緩存之間平衡整個系統的資源. 來自:
www.2cto.com
- 當需要給一個進程分類的時候, 系統會在該進程中處于活動狀態的所有組件里掉選一個重要等級最高作為分類依據. 查看Activity, Service,和IntentReceiver的文檔, 了解每個組件在進程整個生命周期中的貢獻. 每一個classes的文檔詳細描述他們在各自應用的生命周期中所起得作用.
-
實現步驟:
1.繼承Application
public class CustomApplication extends Application{
@Override
public void onCreate(){}
}
繼承Application類
,主要重寫里面的onCreate()
方法(android.app.Application包的onCreate()才是真正的Android程序的入口點)
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對象 Log.i("FirstActivity", "初始值=====" + app.getValue()); // 獲取進程中的全局變量值,看是否是初始化值 app.setValue("Harvey Ren"); // 重新設置值 Log.i("FirstActivity", "修改后=====" + app.getValue()); // 再次獲取進程中的全局變量值,看是否被修改 } }
只需要調用Context
的 getApplicationContext
或者Activity的getApplication方法
來獲得一個Application對象,然后再得到相應的成員變量即可。
-
知識延伸:
MemoryLeak
在Java中內存泄漏是指:某個(某些)對象已經不在被使用應該被gc所回收,但有一個對象持有這個對象的引用而阻止這個對象被回收。比如我們通常會這樣創建一個View TextView tv = new TextView(this);
這里的this
通常都是Activity
。所以這個TextView
就持有著這個Activity的引用。
通常情況下,當用戶轉動手機的時候,android會重新調用OnCreate()
方法生成一個新的Activity,原來的 Activity應該被GC所回收。但如果有個對象比如一個View的作用域超過了這個Activity(比如有一個static
對象或者我們把這個 View
的引用放到了Application
當中),這時候原來的Activity將不能被GC所回收,Activity
本身又持有很多對象的引用,所以 整個Activity的內存被泄漏了。
備注:經常導致內存泄漏核心原因:
keeping a long-lived reference to a Context.持有一個context的對象,從而gc不能回收。
- 1.**一個View的作用域超出了所在的Activity的作用域**,比如一個static的View或者把一個View cache到了application當中 etc
理解:內存:注意靜態的數據和緩存中的數據;注意釋放;
- 2.某些與View關聯的Drawable的作用域超出了Activity的作用域。
- 3.Runnable對象:比如在一個Activity中啟用了一個新線程去執行一個任務,在這期間這個Activity被系統回收了, 但Runnalbe的 任務還沒有執行完畢并持有Activity的引用而泄漏,但這種泄漏一般來泄漏一段時間,只有Runnalbe的線程執行完閉,這個 Activity又可以被正常回收了。
- 4.內存類的對象作用域超出Activity的范圍:比如定義了一個內存類來存儲數據,又把這個內存類的對象傳給了其它Activity 或者Service等。因為內部類的對象會持有當前類的引用,所以也就持有了Context的引用。解決方法
是如果不需要當前的引用把內部類寫成static或者,把內部類抽取出來變成一個單獨的類,或者把避免內部對象作用域超出Activity的作用域。
out Of Memery Error
在android中每一個程序所分到的內存大小是有限的,如果超過了這個數就會報Out Of Memory Error
。
- 注意:所以盡量把程序中的一些大的數據cache到本地文件。以免內存使用量超標。記得數據傳遞完成之后,把存放在application的HashMap中的數據remove掉
,以免發生內存的泄漏。
-
參考資料:
Android中Application類用法
android application 詳解--深入淺出,講解完整的Application,以及所涉及到的擴展知識。
Android筆記 Application對象的使用-數據傳遞以及內存泄漏問題