天天看點

Android Activity全面解析1.Activity生命周期方法完全解析2典型生命周期分析3.與生命周期相關的一些重要方法4.configChange的各種屬性5.Activity的啟動模式

從實習到現在,工作了也快一年了,期間過程也碰到和解決了不少的問題,我的為知筆記上也積累了許許多多零零散散的知識點。個人覺得還是有必要将這些零碎的知識點整體梳理總結一遍這樣才能真正的轉化成真正的技術積累。是以這個專題我主要就是對Android的一些常用知識點以及開發當中遇到的各種問題進行一些梳理與總結。首先,就從Android四大元件Activity開始。

1.Activity生命周期方法完全解析

Android Activity全面解析1.Activity生命周期方法完全解析2典型生命周期分析3.與生命周期相關的一些重要方法4.configChange的各種屬性5.Activity的啟動模式

1).onCreate方法

當Activity第一次建立的時候調用。這個方法裡主要是提供給我們做一些初始化操作,如:建立view、綁定資料到view。同時這個方法裡還帶有一個Bundle參數,這個參數的主要的用途會在後面的onSavedInstanceState方法的介紹裡再來講解。

2).onStart方法

緊接着onCreate方法執行的是onStart方法,該方法的執行表示Activity已經顯示了但是還無法和使用者互動,隻有當執行到onResume方法的時候才可以進行互動。另外提一點,google的文檔裡有寫onStart方法可以直接到onStop方法不經過onResume和onPause,我想了一下就在onStart方法裡調用了一下finish()方法,果不其然onStart後就直接onStop了,但是感覺并沒有什麼卵用是以也就不分析了,有興趣的可以自己實驗一下。

3).onResume方法

調用到onResume方法後,Activity就可以與使用者開始進行互動了,此時Activity就會位于Activity棧的棧頂了。至此一個Activity就完整的呈現在了我們的眼前并可以與之進行互動了。

4).onPause方法

當系統開始準備停止目前Activity的時候調用,在該方法中google給出的建議是存儲一些變化的資料同時停止一些類似于動畫等消耗CPU的工作。該方法的調用過程是很快的,否則會影響到後面的Activity的現實,是以在該方法裡不宜做過多耗時操作。

5).onStop方法

緊接着onPause方法調用,此時Activity已經不再顯示在使用者面前了,此時新的Activity可能已經執行到onStart方法或者onResume方法了,是以此時可做一些較為重量級回收操作比方說關于資料庫的一些讀寫操作等。

6)onRestart方法

onStop方法之後可能會調用到onRestart方法,這是因為代表的Activity正在被重新啟動,然後緊接着就會繼續走到onStart和onResume方法中。

7)onDestroy方法

該方法表示Activity生命周期中的最後一個方法,表示Activity方法将會被銷毀,此時我們可以做一些回收操作。這裡需要提到的一點是,即使一個Activity被銷毀後app内部的static變量是不會被銷毀的,因為static變量是全局的,activity銷毀但是該app的程序并沒有被殺死。是以說這一點尤為需要注意我們的static變量的使用,否則稍有不慎再次啟動該activity的時候該static變量就會是一個dirty data!

2典型生命周期分析

通過上面對生命周期中各個方法的分析我們已經對Activity的各個生命周期方法中所做的事情做了一個完整的梳理,下面就針對幾種典型的生命周期情況進行分析:

Android Activity全面解析1.Activity生命周期方法完全解析2典型生命周期分析3.與生命周期相關的一些重要方法4.configChange的各種屬性5.Activity的啟動模式

下面的分析都是針對一個特定的Activity進行分析:

1).啟動Activity->傳回桌面->再次回到Activity

根據前面對生命周期的分析可以不難知道這三個過程Activity的生命周期方法調用順序如下:

Android Activity全面解析1.Activity生命周期方法完全解析2典型生命周期分析3.與生命周期相關的一些重要方法4.configChange的各種屬性5.Activity的啟動模式

一個Activity,它從啟動到展現在使用者面前的完成毀掉過程是onCreate()->onStart()->onResume()

按HOME鍵傳回桌面:

Android Activity全面解析1.Activity生命周期方法完全解析2典型生命周期分析3.與生命周期相關的一些重要方法4.configChange的各種屬性5.Activity的啟動模式

此時會調用到onPause()->onStop()方法。

當再次回到Activity的時候會調用onRestart()->onStart()方法->onResume()方法:

Android Activity全面解析1.Activity生命周期方法完全解析2典型生命周期分析3.與生命周期相關的一些重要方法4.configChange的各種屬性5.Activity的啟動模式

2).按back退出activity

此時會走onPause()->onStop()->onDestroy()方法:

Android Activity全面解析1.Activity生命周期方法完全解析2典型生命周期分析3.與生命周期相關的一些重要方法4.configChange的各種屬性5.Activity的啟動模式

再次強調的是該方法即使退出了主Activity但是也沒有殺掉程序,是以static變量并沒有被銷毀,再次進來的時候可能會是髒資料。就以我的經驗碰到的最多的一個問題就是:有的時候會将一些名字什麼的存在static變量裡作為全局變量進行調用,此時測試人員的其中一個case會按back退出activity然後切換系統語言再次啟動app。如果沒有對static變量做一些銷毀操作的話,再次回來就是一個dirty data,語言文字并沒有切換導緻了bug的存在。

3).在一個Activity中啟動另一個Activity

從MainActivity中啟動SecondActivity我們可以很清楚的看到MainActivity中的onPause方法執行完了以後然後新的SecondActivity的onCreate、onStart、onResume方法就會依次執行将SecondActivity顯示出來,最後MainActivity的onStop方法才會被調用。這同時也驗證了之前提到的,google并不建議在onPause方法裡進行一些耗時操作。

Android Activity全面解析1.Activity生命周期方法完全解析2典型生命周期分析3.與生命周期相關的一些重要方法4.configChange的各種屬性5.Activity的啟動模式

這裡我們可以做一個暴力一點的實驗,在onPause方法裡調用Thread.sleep(3000)方法讓它睡上三秒,如下圖所示明顯我們可以看到SecondActivity在等待了3秒以後才被執行到,此時的界面會有一個明顯的卡頓住的過程。是以特别強調在onPause方法裡不要做任何耗時操作,同時一些如動畫這樣的消耗CPU性能的操作也需要及時關閉以能最快的啟動新的activity。

Android Activity全面解析1.Activity生命周期方法完全解析2典型生命周期分析3.與生命周期相關的一些重要方法4.configChange的各種屬性5.Activity的啟動模式

3.與生命周期相關的一些重要方法

1)onSaveInstanceState與onRestoreInstanceState方法

前面提在介紹onCreate的時候提到過onCreate方法中帶有一個Bundle參數,我們在正常啟動Activity的時候列印這個參數會發先它是為null的。我們看google文檔可以發現,這個參數隻有當Activity重新初始化的時候才不會為null。那麼什麼叫重新初始化呢?舉一個簡單的例子,比方說手機橫豎屏切換的時候如果我們沒有在manifest檔案的configchange屬性裡指定orientation|screenSize(在android4.0以上必須同時指定這兩個屬性,如果隻寫orientation不生效)就會在onPause之後調用到onSaveInstanceState(Bundle)方法,此時我們就可以往Bundle裡存儲一些資料,随後系統會殺死Activity然後再重新開機它,此時我們發現onCreate方法中的Bundle參數不為空:

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  Log.i(TAG, "MainActivity onCrate");
  if (savedInstanceState != null) {
    Log.i(TAG, "onCreate:" + savedInstanceState.getString(TAG));
  } else {
    Log.i(TAG, "onCreate:" + savedInstanceState);
  }
}

@Override
protected void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  Log.i(TAG, "onSaveInstanceState");
  outState.putString(TAG, "outState");
}
           
Android Activity全面解析1.Activity生命周期方法完全解析2典型生命周期分析3.與生命周期相關的一些重要方法4.configChange的各種屬性5.Activity的啟動模式
Android Activity全面解析1.Activity生命周期方法完全解析2典型生命周期分析3.與生命周期相關的一些重要方法4.configChange的各種屬性5.Activity的啟動模式

我們很容易發現在橫豎屏切換的時候會調用到onSaveInstanceState方法,然後在Activity再次啟動起來的時候onCreate方法中的Bundle就不會為空并且我們可以讀到我們存儲的一些值。雖然在onCreate裡我們可以讀到Bundle的值并取出來使用,但是google更建議的方式還是在onRestoreInstanceState裡來讀這個值。onRestoreInstanceState在onStart方法執行完成後調用,因為此時試圖的初始化工作已經做完了,再取出值來在視圖上進行資料綁定更加合理。

2.onConfigurationChanged方法

3.onNewIntent方法

當我們在manifest檔案裡對Activity的launchmode進行設定為singleTop、singleTask、singleInstance的時候都會有可能調用到此方法。如圖所示:

Android Activity全面解析1.Activity生命周期方法完全解析2典型生命周期分析3.與生命周期相關的一些重要方法4.configChange的各種屬性5.Activity的啟動模式

在這裡我對MainActivity在manifest裡配置了singleTask,首先應用程式起來進入了MainActivity,然我我們通過MainActivity進入到了SecondeActivity,最後通過SecondActivity來再次啟動MainActivity,這個時候因為我們對MainActivity指定的是singleTask模式啟動,是以MainActivity的onNewIntent被調用到了。其實當我們對MainActivity指定為singleTop,singleInstance的時候也同樣會被調用到,究其原因在于該方法主要是用于複用該Activity執行個體的時候調用的。

4.configChange的各種屬性

Android Activity全面解析1.Activity生命周期方法完全解析2典型生命周期分析3.與生命周期相關的一些重要方法4.configChange的各種屬性5.Activity的啟動模式

configchange裡面有這麼多屬性都可以進行配置,下面對其中一些較為常用的進行一番解釋說明。

locate:主要是指系統切換語言

keyboard:代表鍵盤類型發生了變化,比方說由系統的軟鍵盤切換到外置鍵盤

fontScale:使用者在設定裡切換了字号

orientation:螢幕方向發生了變化,不過在android 4.0以上不好使需要同scrennSize一起使用。

5.Activity的啟動模式

Android應用程式都是由一個或多個Activity組成的,而Android内部則是通過棧來對Activity進行管理的。所謂棧就是一個先進後出的資料結構。正常情況下棧頂的Activity就是目前Task顯示的Activity,當我們按back鍵的時候該Activity便會出棧。然而事實并不是這麼簡單,google在對Activity任務棧進行設計的時候考慮到了一些特殊需求是以便有了Activity的啟動模式之說。

Activity的啟動模式包含四種,分别是:standard、singleTop、singleTask、singleInstance,我們可以在manifest裡通過Activity的launchmode進行指定。下面我就逐個介紹一下這四中模式。

1)standard模式

這是Activity的标準啟動模式,如果我們不對Activity做任何特殊處理的情況下就預設為該模式啟動,是以該模式并不需要在manifest或者Intent裡進行指定。這個模式的問題在于會導緻一個任務棧裡會有多個該Activity的執行個體存在,很簡單的一個例子就是我們在AcitivytA裡啟動ActivityA這樣就會有兩個ActivityA存在。假如說該Activity非常消耗資源,那麼就有必要考慮下更改下Activity的啟動模式了。

2)singleTop模式

該模式簡單來說,啟動的Activity已經在任務棧的棧頂話,那麼再啟動這個Activity的時候就不會建立該執行個體,同時會調用該Acitivity的onNewIntent方法(前面有提過該方法)。但是如果該Activity不在棧定的話,那麼啟動它的行為與standard模式并沒有什麼差別。

3)singleTask模式

singleTask指的是一個任務棧中隻能存在一個這樣的Acitivity。但是需要我們注意的是如果任務棧中沒有該Activity的話系統就會幫我們建立一個Acitivity壓入棧頂,但是如果存在該Activity的話就會銷毀壓在該Activity上的所有Activity最終讓建立出來的Activity執行個體處于棧頂,同時也會回掉該Activity的onNewIntent方法。

4)singleInstance模式

該模式是四個模式當中最為特殊的一個,設定了該模式啟動的Acitivyt會在一個獨立的任務棧中開啟,同僚該任務棧有且隻有一個這樣的Activity執行個體,每次再啟動這個Activity的時候就會在該任務棧裡重用該Activity同時回掉onNewIntent方法。

singleInstace與singleTask的差別在于:singleTask啟動的Activity在系統層面上來說是可以有多個執行個體的。比如說應用程式A想調用singleInstance模式下的ActivityA,而應用程式B也同樣調用了,那麼在應用程式A和B中就會各有一個ActivityA的執行個體。但如果該ActivityA是singleInstance模式的話,那麼無論有多少個應用程式調用它,它都隻可能在系統中存在一個執行個體同時該執行個體還是位于它自己的一個單獨的任務棧中。

5).通過Intent中setFlags來指定啟動模式

1.Intent.FLAG_ACTIVITY_NEW_TASK

使用一個新的任務棧來啟動一個Activity,該flag通常用于在Service中啟動Activity的場景,因為Service中并不存在有Activity任務棧是以通常通過這種方式來新啟動一個Activity任務棧并建立新的Activity執行個體。

2.Intent.FLAG_ACTIVITY_SINGLE_TOP

與在manifest檔案裡的launchmode指定”singleTop”作用一樣

3.Intent.FLAG_ACTIVITY_CLEAR_TOP

與在manifest檔案裡的launchmode指定”singleTask”作用一樣

4.Intent.FLAG_ACTIVITY_NO_HISTORY

設定了該Flags的Activity在啟動其他Activity後該Activity就消失了,不會保留在Activity棧中,此Activity可以作為一個中轉Activity來負責啟動其他的Activity。

Activity的常用的基礎知識就這麼多了,關于更加深入的話題如Activity的啟動流程等會在framework學習篇開始探讨。