導讀
- 移動開發知識體系總章(Java基礎、Android、Flutter)
- Application是什么
- Application生命周期
- 使用Application傳遞數據
- 使用Application數據緩存
- Application的context
- Application的oncreate方法會執行幾次,會不會多次執行?
- 使用Application避免一些內存泄漏
Application是什么
Application和Activity、Service一樣是Android框架的一個系統組件,當Android程序啟動時系統會創建一個 Application對象,用來存儲系統的一些信息。
Application的生命周期等于這個程序的生命周期,又因為Application是全局的單例的,所以在不同的Activity,Service中獲得的對象都是同一個對象。所以通過Application來進行一些數據傳遞、數據共享、數據緩存等操作。
一般寫Demo是不需要指定一個Application的,這時系統會自動幫我們創建;而實際項目中基本上都是需要創建自己的Application的,創建一個類繼承 Application并在AndroidManifest清單文件中的Application標簽中進行注冊(只需要給Application標簽增加個name屬性把自己的 Application的名字定入即可)。android系統會為每個程序運行時創建一個Application類的對象且僅創建一個,所以Application可以說是單例 (singleton)模式的一個類。
Application生命周期
- onConfigurationChanged( ) :在配置被改變時觸發 。
- onCreate() :在程序創建時創建。
- onLowMemory() :內存不夠時觸發。
- onTerminate() :當終止程序時調用 但是不能保證一定調用
- onTrimMemory() :在內存清理時觸發
public class App extends Application {
@Override
public void onCreate() {
// 程序創建的時候執行
Log.d(TAG, "onCreate");
super.onCreate();
}
@Override
public void onTerminate() {
// 程序終止的時候執行
Log.d(TAG, "onTerminate");
super.onTerminate();
}
@Override
public void onLowMemory() {
// 低內存的時候執行
Log.d(TAG, "onLowMemory");
super.onLowMemory();
}
@Override
public void onTrimMemory(int level) {
// 程序在內存清理的時候執行
Log.d(TAG, "onTrimMemory");
super.onTrimMemory(level);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
Log.d(TAG, "onConfigurationChanged");
super.onConfigurationChanged(newConfig);
}
}
使用Application傳遞數據
在android中通常會使用Intent(Bundle)進行數據通信,但一般為簡單數據類型,如數據類型相對復雜(如對象)則需要實現 Serializable或者Parcelable接口,其實可以使用Application傳遞復雜數據。
基本思路是這樣的。在Application中創建一個HashMap ,以字符串為key,Object為value這樣我們的HashMap就可以存儲任何類型的對象了
使用Application數據緩存
既然可以在Application中使用HashMap 進行傳遞數據,自然是可以進行一些緩存動作了,不過筆者基本沒有這樣操作過,同時需要注意內存泄漏。
Application的Context
- Context是一個應用程序環境的信息,即上下文。
- 該類是一個抽象(abstract class)類,Android提供了該抽象類的具體實現類(后面我們會講到是ContextIml類)。
-
通過它我們可以獲取應用程序的資源和類,也包括一些應用級別操作,例如:啟動一個Activity,發送廣播,接受Intent信息 等
Context
可以看到Activity、Service、Application都是Context的子類。
也就是說,Android系統的角度來理解:Context是一個場景,代表與操作系統的交互的一種過程。從程序的角度上來理解:Context是個抽象類,而Activity、Service、Application等都是該類的一個實現。
Application的oncreate方法會執行幾次,會不會多次執行?
通常情況下,App默認開啟一個進程,進程名就是AndroidManifest.xml文件中我們項目的包名,所有的基本組件都是在這個進程中進行,Application的onCreate方法會被執行一次
。但是如果我們工程涉及到多進程,那么就會出現Application的onCreate方法被多次執行
情況。
解決oncreate方法多次被調用:
1、定義獲取進程的方法
private String getProcessName(Context context) {
try {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningApps = am.getRunningAppProcesses();
if (runningApps == null) {
return null;
}
for (ActivityManager.RunningAppProcessInfo proInfo : runningApps) {
if (proInfo.pid == android.os.Process.myPid()) {
if (proInfo.processName != null) {
return proInfo.processName;
}
}
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
2、在onCreate方法中進行比對
@Override
public void onCreate() {
super.onCreate();
String processName = getProcessName(this);
if (processName!= null) {
String pkName = this.getPackageName();
//只有主進程,才執行后續邏輯
if(processName.equals(pkName)==false) {
return;
}
}
使用Application避免一些內存泄漏(Memory Leak)
在Java中內存泄漏是指某個(某些)對象已經不在被使用應該被GC回收,但有一個對象持有這個對象的引用而阻止這個對象被回收。
比如在項目中經常用到單例模式,而很多單例是需要傳遞Context的,由于sInstance是一個static且強引用的,若此時傳遞Context的是xxxActivity.this,那么這個xxxActivity就不會被內存回收,就會造成內存泄漏。
解決辦法就是Context傳遞context.getApplicationContext()
ps 經常導致內存泄漏核心原因分析(跳轉連接)
以下內容等待被編輯到指定位置
ps 經常導致內存泄漏核心原因分析(跳轉連接)
keeping a long-lived reference to a Context
上述是常見的內存泄漏的提示,即持有一個context的對象,從而GC不能回收,為什么會有這樣的情況呢
- 一個View的作用域超出了所在的Activity的作用域,比如一個static的View或者把一個View cache到了application
- 某些與View關聯的Drawable的作用域超出了Activity的作用域.
- Runnable對象:比如在一個Activity中啟用了一個新線程去執行一個任務,在這期間這個Activity被系統回收了, 但Runnalbe的 任務還沒有執行完畢并持有Activity的引用而泄漏,但這種泄漏一般來泄漏一段時間,只有Runnalbe的線程執行完閉,這個 Activity又可以被正?;厥樟?。
- 內存類的對象作用域超出Activity的范圍:比如定義了一個內存類來存儲數據,又把這個內存類的對象傳給了其它Activity、Service等。因為內部類的對象會持有當前類的引用,所以也就持有了Context的引用。
解決方法是如果不需要當前的引用把內部類寫成static或者把內部類抽取出來變成一個單獨的類,或者作用域超出Activity的作用域。
Out Of Memery Error 在Android中每一個程序所分到的內存大小是有限的,如果超過了這個數就會報Out Of Memory Error。 Android給程序分配的內存大小與手機硬件有關,以下是一些手機的數據:
G1:16M Droid:24 Nexus One:32M Xoom:48Ms
所以盡量把程序中的一些大的數據cache到本地文件。以免內存使用量超標。
記得數據傳遞完成之后,把存放在application的HashMap中的數據remove掉,以免發生內存的泄漏。