Android 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生命周期

  1. onConfigurationChanged( ) :在配置被改變時觸發 。
  2. onCreate() :在程序創建時創建。
  3. onLowMemory() :內存不夠時觸發。
  4. onTerminate() :當終止程序時調用 但是不能保證一定調用
  5. 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掉,以免發生內存的泄漏。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容