Android 四大元件之 Activity

Keven發表於2019-04-07

讀前思考

學習一門技術或者看一篇文章最好的方式就是帶著問題去學習,這樣才能在過程中有茅塞頓開、燈火闌珊的感覺,記憶也會更深刻。

  1. 說下 Activity 的生命週期?
  2. Activity A 啟動另一個 Activity B 會回撥哪些方法?如果 Activity B 是完全透明呢?如果啟動的是一個 Dialog 呢?
  3. 談談 onSaveInstanceState() 方法?何時會呼叫?
  4. 如何避免配置改變時 Activity 重建?
  5. 優先順序低的 Activity 在記憶體不足被回收後怎樣做可以恢復到銷燬前狀態?
  6. 說下 Activity 的四種啟動模式?分別會在什麼時候使用?
  7. onNewIntent()呼叫時機?
  8. 如何啟動其他應用的Activity?

Activity 生命週期

onCreate() -> onStart() - > onResume() -> onPause() -> onStop() -> onDestroy()

Android 四大元件之 Activity

  • onCreate(): 在活動第一次被建立時會呼叫,可以在這個方法中完成初始化操作,如:佈局載入、繫結事件等。
  • onStart(): 在活動由不可見變為可見時候呼叫。
  • onResume(): 在返回棧頂端,獲得焦點,可以和使用者進行互動。
  • onPause: 失去焦點,系統去啟動另一個活動時候會呼叫,可以在這裡做一些資料儲存,資源釋放,但不能做耗時操作。
  • onStop: 活動完全不可見時呼叫。
  • onDestroy: 活動被銷燬時呼叫。
  • onRestart: 活動由後臺不可見變為前臺可見時候呼叫。

啟動 Activity

A 啟動 B

重寫 A 和 B 的生命週期方法

A 啟動 B

com.keven.jianshu E/TAG: A 的 onPause()
com.keven.jianshu E/TAG: B 的 onCreate()
com.keven.jianshu E/TAG: B 的 onStart()
com.keven.jianshu E/TAG: B 的 onResume()
com.keven.jianshu E/TAG: A 的 onStop()
複製程式碼

從 B 返回 A

com.keven.jianshu E/TAG: B 的 onPause()
com.keven.jianshu E/TAG: A 的 onRestart()
com.keven.jianshu E/TAG: A 的 onStart()
com.keven.jianshu E/TAG: A 的 onResume()
com.keven.jianshu E/TAG: B 的 onStop()
com.keven.jianshu E/TAG: B 的 onDestroy()
複製程式碼

A 啟動透明的 B (或者 Dialog 形式)

com.keven.jianshu E/TAG: A 的 onPause()
com.keven.jianshu E/TAG: B 的 onCreate()
com.keven.jianshu E/TAG: B 的 onStart()
com.keven.jianshu E/TAG: B 的 onResume()
複製程式碼

onSaveInstanceState

異常情況下的生命週期:比如當系統資源配置發生改變以及系統記憶體不足時,activity 就可能被殺死或者銷燬後重建。

1. Activity 橫豎屏切換
com.keven.jianshu E/TAG: A 的 onCreate()
com.keven.jianshu E/TAG: A 的 onCreate() 中 savedInstanceState 是空的嗎?true
com.keven.jianshu E/TAG: A 的 onStart()
com.keven.jianshu E/TAG: A 的 onResume()
com.keven.jianshu E/TAG: A 的 onPause()
com.keven.jianshu E/TAG: A 的 onStop()
com.keven.jianshu E/TAG: A 的 onSaveInstanceState()
com.keven.jianshu E/TAG: A 的 onDestroy()
com.keven.jianshu E/TAG: A 的 onCreate()
com.keven.jianshu E/TAG: A 的 onCreate() 中 savedInstanceState 是空的嗎?false
com.keven.jianshu E/TAG: A 的 onStart()
com.keven.jianshu E/TAG: A 的 onRestoreInstanceState()
com.keven.jianshu E/TAG: A 的 onResume()
複製程式碼

可以看到橫豎屏切換時,會呼叫 onSaveInstanceState( )進行狀態儲存,再次建立時,會呼叫 onRestoreInstanceState( ) 方法進行資料的恢復。

解決辦法:
可以通過在清單檔案中設定如下屬性,避免橫豎屏切換時重新建立。

android:configChanges="orientation|screenSize"
複製程式碼
2、記憶體不足時

資源記憶體不足導致低優先順序的 activity 被殺死
這裡的情況和前面橫豎屏切換的資料儲存和恢復是完全一致的,activity 按照優先順序從高到低可以分為如下三種:

  1. 前臺 activity: 正在和使用者互動的 activity,優先順序最高
  2. 可見但非前臺 activity,比如 activity 中彈出了一個對話方塊,導致 activity 可見但是位於後臺無法和使用者直接互動。
  3. 後臺 activity,已經被暫停的 activity,比如執行了 onStop,優先順序最低。

啟動模式

standard-預設模式

這個模式是預設的啟動模式,即標準模式,在不指定啟動模式的前提下,系統預設使用該模式啟動 Activity,每次啟動一個 Activity 都會重寫建立一個新的例項,不管這個例項存不存在,這種模式下,誰啟動了該模式的 Activity,該 Activity 就屬於啟動它的 Activity 的任務棧中。

singleTop-棧頂複用模式

這個模式下,如果新的 activity 已經位於棧頂,那麼這個 Activity 不會被重寫建立,同時它的 onNewIntent 方法會被呼叫,通過此方法的引數我們可以去除當前請求的資訊。如果棧頂不存在該 Activity 的例項,則情況與 standard 模式相同。需要注意的是這個 Activity 它的 onCreate(),onStart() 方法不會被呼叫,因為它並沒有發生改變。

singleTask-棧內複用模式

在這個模式下,如果棧中存在這個 Activity 的例項就會複用這個 Activity,不管它是否位於棧頂,複用時,會將它上面的 Activity 全部出棧,並且會回撥該例項的 onNewIntent 方法。其實這個過程還存在一個任務棧的匹配,因為這個模式啟動時,會在自己需要的任務棧中尋找例項,這個任務棧就是通過 taskAffinity 屬性指定。如果這個任務棧不存在,則會建立這個任務棧。

singleInstance-全域性唯一模式

該模式具備 singleTask 模式的所有特性外,與它的區別就是,這種模式下的 Activity 會單獨佔用一個Task棧,具有全域性唯一性,即整個系統中就這麼一個例項,由於棧內複用的特性,後續的請求均不會建立新的 Activity 例項,除非這個特殊的任務棧被銷燬了。以 singleInstance 模式啟動的 Activity 在整個系統中是單例的,如果在啟動這樣的 Activiyt 時,已經存在了一個例項,那麼會把它所在的任務排程到前臺,重用這個例項。

隱式啟動

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

IntentFilter 匹配規則:

  1. 一個 intent 只有同時匹配某個 Activity 的 intent-filter 中的 action、category、data 才算完全匹配,才能啟動該 Activity。
  2. 一個 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 中也必須也要定義 data。 data 主要由 mimeType (媒體型別)和 URI 組成。在匹配時通過 intent.setDataAndType(Uri data, String type) 方法對 date 進行設定。

使用 H5 通過隱式啟動的方式開啟 Activity 可參考 WebView 通過隱式啟動跳轉到Activity頁面

文章已經讀到末尾了,不知道最初的幾個問題你都會了嗎?如果不會的話?可以再針對不會的問題進行精讀哦!答案都在文中,相信你肯定可以解決的!

相關文章