要點提煉|開發藝術之 Activity

本系列專題以提煉要點的方式總結知識點,而不做具體展開,對應的會附上個人較喜歡的文章鏈接供大家詳細瞭解和學習。第一個板塊開發藝術 是對任老師的《Android開發藝術探索》著作的學習和擴展,此書的目錄也是該板塊的主線,那麼就先從我們熟悉的Activity開始吧~

在之前的Activity篇主要學習Activity的生命週期、創建和頁面跳轉的實現,本篇將深入瞭解Activity,學習清單:

  • 生命週期全解析
  • 四種啓動模式
  • IntentFilter匹配規則

一.生命週期全解析

1.Q:典型情況下Activity生命週期
A:
a.onCreate():

  • 狀態:Activity 正在創建
  • 任務:做初始化工作,如setViewContent界面資源、初始化數據
  • 注意:此方法的傳參Bundle爲該Activity上次被異常情況銷燬時保存的狀態信息。

b.onStart():

  • 狀態:Activity 正在啓動,這時Activity 可見但不在前臺,無法和用戶交互。

c.onResume():

  • 狀態:Activity 獲得焦點,此時Activity 可見且在前臺並開始活動。

d.onPause():

  • 狀態: Activity 正在停止
  • 任務:可做 數據存儲、停止動畫等操作。
  • 注意:Activity切換時,舊Activity的onPause會先執行,然後纔會啓動新的Activity。

e.onStop():

  • 狀態:Activity 即將停止
  • 任務:可做稍微重量級回收工作,如取消網絡連接、註銷廣播接收器等。
  • 注意:新Activity是透明主題時,舊Activity都不會走onStop。

f.onDestroy():

  • 狀態:Activity 即將銷燬
  • 任務:做回收工作、資源釋放

g.onRestart():

  • 狀態:Activity 重新啓動,Activity由後臺切換到前臺,由不可見到可見。

onStart()和onResume()、onPause()和onStop()的區別: onStart與onStop是從Activity是否可見這個角度調用的,onResume和onPause是從Activity是否顯示在前臺這個角度來回調的,在實際使用沒其他明顯區別。

推薦閱讀:對Activity生命週期方法的感性理解

2.Activity生命週期的切換過程
①啓動一個Activity:

  • onCreate()–>onStart()–>onResume()

②打開一個新Activity:

  • 舊Activity的onPause() –>新Activity的onCreate()–>onStart()–>onResume()–>舊Activity的onStop()

③返回到舊Activity:

  • 新Activity的onPause()–>舊Activity的onRestart()–>onStart()–>onResume()–>新Activity的onStop()–>onDestory();

④Activity1上彈出對話框Activity2:

  • Activity1的onPause()–>Activity2的onCreate()–>onStart()–>onResume()

⑤關閉屏幕/按Home鍵:

  • Activity2的onPause()–>onStop()–>Activity1的onStop()

⑥點亮屏幕/回到前臺:

  • Activity2的onRestart()–>onStart()–>Activity1的onRestart()–>onStart()–>Activity2的onResume()

⑦關閉對話框Activity2:

  • Activity2的onPause()–>Activity1的onResume()–>Activity2的onStop()–>onDestroy()

⑧銷燬Activity1:

  • onPause()–>onStop()–>onDestroy()

參考文章:實際體驗Activity生命週期

3.Q:生命週期的各階段
A:
a.完整生命週期
Activity在onCreate()和onDestroy()之間所經歷的。
在onCreate()中完成各初始化操作,在onDestroy()中釋放資源。

b.可見生命週期
Activity在onStart()和onStop()之間所經歷的。
活動對於用戶是可見的,但仍無法與用戶進行交互。

c.前臺生命週期
Activity在onResume()和onPause()之間所經歷的。
活動可見,且可交互。

4.onSaveInstanceState和onRestoreInstanceState
a.出現時機:異常 情況下Activity 重建,非用戶主動去銷燬

b.系統異常終止時,調用onSavaInstanceState來保存狀態。該方法調用在onStop之前,但和onPause沒有時序關係。

onSaveInstanceState與onPause的區別:前者適用於對臨時性狀態的保存,而後者適用於對數據的持久化保存。

c.Activity被重新創建時,調用onRestoreInstanceState(該方法在onStart之後),並將onSavaInstanceState保存的Bundle對象作爲參數傳到onRestoreInstanceState與onCreate方法。

可通過onRestoreInstanceState(Bundle savedInstanceState)和onCreate((Bundle savedInstanceState)來判斷Activity是否被重建,並取出數據進行恢復。但需要注意的是,在onCreate取出數據時一定要先判斷savedInstanceState是否爲空。另外,谷歌更推薦使用onRestoreInstanceState進行數據恢復。

推薦閱讀onSaveInstanceState和onRestoreInstanceState詳解

5.Activity異常情況下生命週期分析

a.由於資源相關配置發生改變,導致Activity被殺死和重新創建
例如屏幕發生旋轉:當豎屏切換到橫屏時,會先調用onSaveInstanceState來保存切換時的數據,接着銷燬當前的Activity,然後重新創建一個Activity,再調用onRestoreInstanceState恢復數據。

  • onSaveInstanceState–>onPause(不定)–>onStop–>
    onDestroy–>onCreate–>onStart–>onRestoreInstanceState–>onResume

爲了避免由於配置改變導致Activity重建,可在AndroidManifest.xml中對應的Activity中設置android:configChanges=”orientation|keyboardHidden|screenSize”。此時再次旋轉屏幕時,該Activity不會被系統殺死和重建,只會調用onConfigurationChanged。因此,當配置程序需要響應配置改變,指定configChanges屬性,重寫onConfigurationChanged方法即可。

b.由於系統資源不足,導致優先級低的Activity被回收
①Activity優先級排序:

  • 前臺可見Activity>前臺可見不可交互Activity(前臺Activity彈出Dialog)>後臺Activity(用戶按下Home鍵、切換到其他應用)

②當系統內存不足時,會按照Activity優先級從低到高去殺死目標Activity所在的進程。

③若一個進程沒有四大組件在執行,那麼這個進程將很快被系統殺死。

推薦閱讀異常情況下的生命週期分析


二.Activity四種啓動模式

1.Q:設置Activity啓動模式的方法
A:
a.在AndroidManifest.xml中給對應的Activity設定屬性android:launchMode=”standard|singleInstance|single Task|singleTop”。
b.通過標記位設定,方法是intent.addFlags(Intent.xxx)

2.Q:Activity的四種LaunchMode
A:
a.standard:標準模式、默認模式
- 含義:每次啓動一個Activity就會創建一個新的實例。
- 注意:使用ApplicationContext去啓動standard模式Activity就會報錯。因爲standard模式的Activity會默認進入啓動它所屬的任務棧,但是由於非Activity的Context沒有所謂的任務棧。

b.singleTop:棧頂複用模式

  • 含義:如果新Activity已經位於任務棧的棧頂,就不會重新創建,並回調onNewIntent(intent)方法。

c.singleTask:棧內複用模式

  • 含義:只要該Activity在一個任務棧中存在,都不會重新創建,並回調onNewIntent(intent)方法。如果不存在,系統會先尋找是否存在需要的棧,如果不存在該棧,就創建一個任務棧,並把該Activity放進去;如果存在,就會創建到已經存在的棧中。

d.singleInstance:單實例模式

  • 含義: 具有此模式的Activity只能單獨位於一個任務棧中,且此任務棧中只有唯一一個實例。

標識Activity任務棧名稱的屬性:android:taskAffinity,默認爲應用包名。

推薦閱讀:Activity的四種LaunchMode詳解

3.常用的可設定Activity啓動模式的標記位

FLAG_ACTIVITY_SINGLE_TOP:對應singleTop啓動模式。
FLAG_ACTIVITY_NEW_TASK :對應singleTask模式。


三.IntentFilter匹配規則

原則:
①一個intent只有同時匹配某個Activity的intent-filter中的action、category、data纔算完全匹配,才能啓動該Activity。
② 一個Activity可以有多個 intent-filter,一個 intent只要成功匹配任意一組 intent-filter,就可以啓動該Activity。

a. action匹配規則:

  • 要求intent中的action 存在且必須和intent-filter中的其中一個 action相同。
  • 區分大小寫。

b. category匹配規則:

  • intent中的category可以不存在,這是因爲此時系統給該Activity 默認加上了< category android:name=”android.intent.category.DEAFAULT” />屬性值。
  • 除上述情況外,有其他category,則要求intent中的category和intent-filter中的所有 category 相同。

c. data匹配規則:

  • 如果intent-filter中有定義data,那麼Intent中也必須也要定義date。
  • data主要由mimeType(媒體類型)和URI組成。在匹配時通過intent.setDataAndType(Uri data, String type)方法對date進行設置。
  • 要求和action相似:如果沒有指定URI,默認值爲content和file; 有多組data規則時,匹配其中一組即可。

採用隱式方式啓動Activity時,可以用PackageManager的resolveActivity方法或者Intent的resolveActivity方法判斷是否有Activity匹配該隱式Intent。

推薦閱讀:Intent和IntentFilter


希望這篇文章對你有幫助~

發佈了51 篇原創文章 · 獲贊 33 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章