1. 程式人生 > >《Android中高階工程師面試指南 — 基礎知識 — Activity》

《Android中高階工程師面試指南 — 基礎知識 — Activity》

一、Activity的生命週期

1、Android程序優先順序

Q: 請簡述Android程序的優先順序?
A: Android系統往往傾向於延長應用程式的程序,以提高效率,但是當系統記憶體不足的時候,也需要殺死一些程序來回收資源,而決定殺死哪些程序的一項重要參考指標就是程序的優先順序。Android系統根據在程序中在執行的元件及元件的狀態,為每一個程序分配了一個優先順序等級,優先順序最低的程序首先被殺死。
  在Android系統中,程序根據不同的優先順序可以分為5個常用等級:前臺程序、可見程序、服務程序、後臺程序、空程序。Android系統會盡可能高地評估一個程序的優先順序,同時一個程序的優先順序可能會由於其它程序的依賴而升高。
  前臺程序

,指使用者當前做的事所必須的程序,如果一個程序滿足以下下一個條件則被認為是前臺程序:
  1、程序持有一個正在與使用者互動的Activity。
  2、程序持有一個Service,這個Service處於這幾種狀態:a、Service與使用者正在互動的Activity繫結;b、Service是在前臺執行的,即它呼叫了startForeground();c、Service正在執行它的生命週期回撥函式(onCreate(),onStart(),onDestroy())。
  3、程序持有一個BroadcastReceiver,這個BroadcastReceiver正在執行它的 onReceive() 方法。
  前臺程序的優先順序是最高的,Android系統一般情況下不會殺死一個前臺程序。
  可見程序
,不含有任何前臺的元件,但仍可被使用者在螢幕上所見的程序。如果一個程序滿足以下下一個條件則被認為是可見程序:
  1、程序持有一個Activity,這個Activity不在前臺,但是仍然被使用者可見(處於onPause()呼叫後又沒有呼叫onStop()的狀態,比如,前臺的activity打開了一個對話方塊,這樣activity就會在其後可見)。
  2、程序持有一個Service,這個Service和一個可見的Activity繫結。
  可見的程序也是很重要的,一般不會被系統銷燬,除非為了保證所有前臺程序正常執行而不得不殺死可見程序。
  服務程序,如果一個程序中執行著一個service,這個service是通過 startService() 開啟的,並且不屬於上面兩種較高優先順序的情況,這個程序就是一個服務程序。
  儘管服務程序沒有和使用者可以看到的東西繫結,但是它們一般在做的事情是使用者關心的,比如後臺播放音樂,後臺下載資料等。所以系統會盡量維持它們的執行,除非系統記憶體不足以維持前臺程序和可見程序的執行需要。
  後臺程序
,如果程序不屬於上面三種情況,但是程序持有一個使用者不可見的activity(activity的onStop()被呼叫,但是onDestroy()沒有呼叫的狀態),就認為程序是一個後臺程序。
  後臺程序不直接影響使用者體驗,系統會為了前臺程序、可見程序、服務程序而任意殺死後臺程序。
  通常會有很多個後臺程序存在,它們會被儲存在一個LRU列表中,這樣就可以確保使用者最近使用的Activity最後被銷燬。
  空程序 如果一個程序不包含任何活躍的應用元件,則認為是空程序。例如:一個程序當中已經沒有資料在運行了,但是記憶體當中還為這個應用駐留了一個程序空間。 儲存這種程序的唯一理由是為了快取的需要,為了加快下次要啟動這個程序中的元件時的啟動時間。
  空程序通常最先被系統殺死。

2、Activity的四種狀態

Q:Activity有哪幾種狀態?
A: 每個activity在其生命週期內最多會經歷四種狀態:執行狀態、暫停狀態、停止狀態、銷燬狀態。
  執行狀態(running):activity處於任務棧的棧頂,此時它處於可見並可和使用者互動的啟用狀態。
  暫停狀態(paused):activity不再處於棧頂,但是仍然可見,這時activity就處於暫停狀態。比如,activity被另一個透明或者Dialog樣式的activity覆蓋。此時它依然與視窗管理器保持連線,系統繼續維護其內部狀態,它仍然可見,但它已經失去了焦點,故不可與使用者互動。
  停止狀態(stopped):activity不再處於棧頂且完全不可見的時候,這時activity就處於停止狀態。這種狀態下這個activity是否繼續存活取決於系統記憶體是否充足。
  銷燬狀態(destroyed): activity被殺掉以後或者被啟動以前,這時activity處於銷燬狀態。這時activity已從activity任務棧中移除,需要重新啟動才可以顯示和使用。

3、Activity的生命週期

  以下這張圖得記住!
Activity生命週期

Q:請簡述Activity的生命週期?
A: Activity常用的生命週期回掉函式包括:onCreate()、onStart()、onResume()、onPause()、onStop()、onDestroy()、onRestart()。
  onCreate():create表示建立,這是Activity生命週期的第一個方法,它的作用是進行Activity的一些初始化工作,比如使用setContentView載入佈局,對一些控制元件和變數進行初始化等。
  onStart():start表示啟動,這時activity正在被啟動,即將開始,activity正在從不可見到可見,但此時activity還在後臺,還無法與使用者互動。
  onResume():resume表示繼續、重新開始,這時activity已經可見,且可以和使用者互動,此時activity一定是處於任務棧的棧頂,一定是在前臺。
  onPause():pause表示暫停,當activity要跳到另一個activity或應用正常退出時都會執行這個方法
  onStop():stop表示停止,此時activity已經不可見了,但是activity物件還在記憶體中,沒有被銷燬。
  onDestroy():destroy表示毀滅, 此時activity正在被銷燬,可以做回收工作,資源釋放,解除繫結等。
  onRestart():表示activity正在重新啟動,一般情況,當activity從不可見變成可見的時候,該方法就會被呼叫。
  通常情況下,當我們啟動activity,系統會先呼叫onCreate方法,然後呼叫onStart方法,最後呼叫onResume,activity進入執行狀態。如果當前activity被其他activity覆蓋或被鎖屏,系統會呼叫當前activity的onPause方法,暫停當前activity的執行。如果當前activity由被覆蓋狀態回到前臺或解鎖屏,這時系統會呼叫當前activity的onResume方法,再次進入執行狀態。如果當前activity轉到新的activity介面或按Home鍵回到主屏,當前activity退居後臺,則系統會先呼叫當前activity的onPause方法,然後呼叫onStop方法,當前activity進入停滯狀態。如果這時使用者後退回到此activity,則系統會先呼叫此activity的onRestart方法,然後呼叫onStart方法,最後呼叫onResume方法,此activity再次進入執行狀態。如果當前Activity處於被覆蓋狀態或者後臺不可見狀態,這時系統記憶體不足並且殺死了當前的activity,而後使用者退回當前activity,則再次呼叫當前activity的onCreate方法、onStart方法、onResume方法,進入執行狀態。如果使用者退出當前activity:系統先呼叫onPause方法,然後呼叫onStop方法,最後呼叫onDestory方法,結束當前activity。

4、異常情況下Activity的生命週期

Q:在系統配置發生變化時,比如橫豎屏發生了變化,請簡述此時Activity的生命週期以及如何解決?
A: 在預設情況下,當系統配置發生改變後,如果我們的Activity不做特殊處理,Activity就會被銷燬並重新建立。
  Activity被銷燬時,它的onPause()、onStop()和onDestory()方法均會被呼叫,同時系統配置發生改變屬於異常情況,這個時候系統會呼叫Activity的onSaveInstanceState()方法來儲存當前Activity的狀態。onSaveInstanceState()方法的呼叫時機是在onStop()方法之前,它和onPause()沒有既定的時序關係,它既可能在onPause()之前呼叫,也可能在onPause()之後呼叫。(注:這個方法只會出現在Activity被異常終止的情況下,正常情況下系統不會回撥這個方法,異常情況也包括Activity被系統殺死等)。
  Activity被重新建立時,系統會呼叫Activity的onRestoreInstanceState()方法,並且把Activity銷燬時onSaveInstanceState()方法所儲存的Bundle物件作為引數同時傳遞給onRestoreInstanceState()和onCreate()方法,這個時候我們就可以取出之前儲存的資料並恢復。(當我們恢復資料時,可以選擇onRestoreInstanceState()或者onCreate(),二者的區別是:onRestoreInstanceState()一旦被呼叫,其引數Bundle savedInstanceState 一定是有值的,我們不用額外的判斷是否為空,但是onCreate()不行,onCreate()如果是正常啟動的話,其引數Bundle savedInstanceState為null,所以必須額外判斷,這兩個方法任意一個都可以進行資料恢復,官方文件建議採用onRestoreInstanceState()去恢復資料。從時序來說,onRestoreInstanceState()的呼叫時機在onStart()之後)
  同時,在onSaveInstanceState()和onRestoreInstanceState()方法中,系統自動為我們做了一定的恢復工作,當Activity在異常情況下需要重新建立時,系統會預設為我們儲存當前Activity的檢視結構,並且在Activity重啟後為我們恢復這些資料,比如文字框中使用者輸入的資料,ListView滾動的位置等。這些View相關的狀態系統都能夠預設為我們恢復。(注:和Activity一樣,每個View都有onSaveInstanceState()和onRestoreInstanceState()這兩個方法)
  系統配置中有很多內容,如果當某項內容發生改變後,我們不想系統重新建立Activity,可以給Activity設定configChanges屬性。比如不想讓Activity在螢幕旋轉的時候重新建立,就可以給configChanges屬性新增orientation這個值: android:configChanges=”orientation”。當SDK版本大於13時,還需增加srceenSize。

二、Android的任務棧

Q:請簡述Android的任務棧機制?
A: 在Android系統中,任務是一個Activity的集合,它使用棧的方式來管理其中的Activity,這個棧又被稱為返回棧(back stack),棧中Activity的順序就是按照它們被開啟的順序依次存放的,是一個典型的後進先出的資料結構。
  當一個Activity啟動了另外一個Activity的時候,新的Activity就會被放置到返回棧的棧頂並將獲得焦點。前一個Activity仍然保留在返回棧當中,但會處於停止狀態。當用戶按下Back鍵的時候,棧中最頂端的Activity會被移除掉,然後前一個Activity則會得重新回到最頂端的位置。預設情況下,一個Activity在任務棧中可以被例項化多次。
  當用戶通過Home鍵離開一個任務時,該任務會進入後臺,並且返回棧中所有的Activity都會進入停止狀態。系統會將這些Activity的狀態進行保留,這樣當用戶下一次重新開啟這個應用程式時,就可以將後臺任務直接提取到前臺,並將之前最頂端的Activity進行恢復。
  如果使用者將任務切換到後臺之後過了很長一段時間,系統會將這個任務中除了最底層的那個Activity之外的其它所有Activity全部清除掉。當用戶重新回到這個任務的時候,最底層的那個Activity將得到恢復。
  上述則是Android預設的任務棧管理機制,我們想改變這種預設方式,可以在manifest檔案中設定activity元素的屬性,或者是在啟動Activity時配置Intent的flag。在activity元素的屬性中,我們可以配置taskAffinity、launchMode、allowTaskReparenting、clearTaskOnLaunch、alwaysRetainTaskState、finishOnTaskLaunch等,在Intent當中,常用的flag包括:FLAG_ACTIVITY_NEW_TASK、FLAG_ACTIVITY_CLEAR_TOP、FLAG_ACTIVITY_SINGLE_TOP。

三、Activity的啟動模式

Q:請簡述Activity的四種啟動模式?
A: 當我們在manifest檔案中定義Activity的時候,可以通過activity元素的launchMode屬性來指定這個Activity應該如何與任務進行關聯。launchMode也就是啟動模式,一共分為四種:
  ”standard”(預設啟動模式):如果不指定launchMode屬性,則自動就會使用這種啟動模式。這種啟動模式表示每次啟動該Activity時系統都會為建立一個新的例項,並且總會把它放入到當前的任務當中。宣告成這種啟動模式的Activity可以被例項化多次,一個任務當中也可以包含多個這種Activity的例項。
  ”singleTop”(棧頂複用模式):如果要啟動的這個Activity在當前任務中已經存在了,並且還處於棧頂的位置,那麼系統就不會再去建立一個該Activity的例項,而是呼叫棧頂Activity的onNewIntent()方法。宣告成這種啟動模式的Activity也可以被例項化多次,一個任務當中也可以包含多個這種Activity的例項。
  ”singleTask”(棧內複用模式):如果現有任務當中已經存在一個該Activity的例項了,那麼系統就不會再建立一次它的例項,而是會直接呼叫它的onNewIntent()方法。宣告成這種啟動模式的Activity,在同一個任務當中只會存在一個例項。
  ”singleInstance”(單例模式):這種啟動模式和”singleTask”有點相似,只不過系統不會向宣告成”singleInstance”的Activity所在的任務當中再新增其它Activity。也就是說,這種Activity所在的任務中始終只會有一個Activity,通過這個Activity再開啟的其它Activity也會被放入到別的任務當中。

  注:本篇部落格開始,後期會推出《Android中高階工程師面試指南》系列部落格,該系列部落格收錄一些Android中高階工程師面試時經常遇到的面試題,內容包括:Android基礎知識面試講解、訊息機制和多執行緒面試講解、網路協議和網路框架面試講解、View相關面試講解、效能優化面試講解、設計模式和架構設計面試講解、Android原始碼相關面試講解、前沿技術面試講解。希望能夠幫助各位讀者找到心儀的工作。
  注:在Android中高階工程師面試的時候,基礎知識一般會問的比較細,面試官會通過一些技術細節來判斷你的技術水平,所以基礎知識這部分一定要好好準備,尤其是一些細節。
  注:能力有限,水平一般,如果文章中有錯誤,歡迎大家留言指正。如果大家覺得文章寫的不錯,對技術水平的提升還有點幫助,掃描下面的二維碼,打賞筆者一瓶水錢也是極好的~~~
這裡寫圖片描述