回覆列表
  • 1 # 使用者9554196802473

    Activity 是什麼

    簡單的來說,一個 Activity 包含了使用者可以看到的介面,用來和使用者進行互動。一個應用程式中可以有零個或者多個 Activity。零個 Activity 的話就是,這個程式不包含與使用者互動的介面。

    返回棧(任務棧)(任務)

    Android 是使用任務(Task)來管理 Activity 的。一個 Task 就是一組存放在棧裡的 Activity 的集合。這個任務也被稱為返回棧(Back Stack),棧是一種先進先出的資料結構,預設情況下,每當我們啟動了一個新的 Activity,它會被加入到棧中,並處於棧頂的位置,當 Activity 的 finish 方法去銷燬一個 Activity 的時候,這個 Activity 就會出棧。系統總是會顯示處於棧頂的 Activity 給使用者。

    Activity 的狀態

    每個 Activity 在其生命週期中最多可能會有 4 中狀態

    執行狀態

    當一個 Activity 位於返回棧的棧頂的時候,這個時候這個 Activity 就處於執行狀態。這個時候是最不容易被系統回收的。

    暫停狀態

    當一個 Activity 不再處於棧頂位置,但是仍然可見的時候,這種情況下這個 Activity 就處於暫停狀態。Activity 不在棧頂了竟然還能被看到?你想如果棧頂的 Activity 是一個對話方塊或者是透明的情況下,是不是這個不在棧頂位置的 Activity 依然可以被使用者看到啊。這種狀態的 Activity,系統也是不願意去回收的。

    停止狀態

    當一個 Activity 不再處於棧頂位置,而且完全看不到的時候,就進入了停止狀態了。系統仍然會為這樣的 Activity 保留響應的狀態和成員變數,但這並不是完全可靠的,當記憶體緊張的時候,處於停止狀態的 Activity 有可能被系統回收。

    銷燬狀態

    當一個 Activity 從返回棧移除後就變成銷燬狀態了,系統傾向回收處於這種狀態的 Activity

    Activity 的生命週期

    先放上一張最經典的圖

    image.png

    onCreate()

    會在 Activity 第一次被建立的時候呼叫,應該在這個方法中完成 Activity 的初始化操作,比如載入佈局、繫結事件等等。

    onStart()

    Activity 由不可見狀態變為可見狀態。

    onResume()

    這個方法在 Activity 準備好和使用者進行互動的時候呼叫,此時 Activity 一定處於返回棧的棧頂,並且處於執行狀。

    onPause()

    這個方法在系統準備去啟動或者恢復另一個 Activity 的時候呼叫。通常會在這個方法中將一些消耗 CPU 的資源釋放,儲存一些關鍵的資料,但是這個方法的執行速度一定要快,不然會影響新的棧頂 Activity 的使用。

    onStop()

    在 Activity 完全不可見的時候呼叫。

    onDestroy()

    這個方法在被銷燬之前呼叫,之後 Activity 的狀態就變為銷燬狀態。

    onRestart()

    這個方法在 Activity 由停止狀態變為執行狀態之前呼叫,也就是 Activity 被重新啟動了。

    以上 7 個方法中除了 onRestart 方法,其他都是兩輛相對的,從而又可以將 Activity 分為 3 中生存期。

    完整生存期:Activity 在 onCreate 和 onDestroy 方法之間所經歷的,就是完整的生存期。一般情況下,我們需要在 onCreate 方法中完成各種初始化操作,在 onDestroy 中完成釋放記憶體的操作。可見生存期:Activity 在 onStart 和 onStop 之間所經歷的,就是可見生存期。在可見生存期,Activity 對於使用者總是可見的,但是可能無法和使用者互動。我們可以透過這兩個方法來合理的管理那些對使用者可見的資源。在 onStart 方法中對資源進行載入,在 onStop 方法中對資源進行釋放,從而使得處於停止狀態的 Activity 不會佔用太多記憶體。前臺生存期:Activity 在 onResume 和 onPause 方法之間所經歷的就是前臺生存期。此時的 Activity 是可以和使用者進行互動的。

    特別情況下的生命週期

    上面都是正常情況的下面生命週期,下面來幾個比較有特點的生命週期。

    Activity A 啟動後,啟動一個正常的 Activity B,這時 A 的生命週期:onCreate ->onStart -> onResume -> onPause -> onStop -> B 的生命週期。Activity A 啟動後,啟動一個 Dialog 樣式或者透明的 Activity B,這時 A 的生命週期 onCreate ->onStart -> onResume -> onPause -> B 的生命週期。鎖屏狀態和按下 HOME 鍵的時候 Activity 都是會執行 onStop 的旋轉螢幕的情況:Activity 的生命週期是會重新開始的。比如當前 Activity 處於豎屏,然後旋轉成橫屏,這個時候 Activity 會執行 onPause onStop onDestroy,由於是在異常情況下終止的,系統會呼叫 onSaveInstance 來儲存當前 Activity 的狀態。Activity 先回調 onResume 後 onCreateOptionsMenu

    Activity 意外終止

    Activity 進入停止狀態後,就有可能被系統回收。Activity 為我們提供了一個方法 onSaveInstanceState() 回撥方法,這個方法可以保證在 Activity 被回收之前一定會被呼叫,我們可以透過這個方法來儲存一些臨時資料。

    Activity 的啟動模式

    啟動模式一共有 4 中:standard、singleTop、singTask 和 singleInstance,可以在 AndroidManifest.xml 中透過 <activity> 標籤指定 android:launchMode 屬性來選擇啟動模式。

    standard 模式

    standard 模式是 Activity 的預設啟動模式,在不進行顯示指定的情況下,所有 Activity 都會自動使用這種啟動模式。這種模式下,每當啟動一個新的 Activity,它就會在返回棧的棧頂位置。對於使用 standard 模式啟動的 Activity,系統不會在乎這個 Activity 是否已經存在在棧中了。每次啟動的時候都會建立一個新的例項。

    誰啟用了這個模式的 Activity,那麼這個 Activity 就屬於啟動它的 Activity 的任務棧。

    singleTop 模式

    如果 Activity 指定為 singleTop,在啟動 Activity 的時候發現返回棧的棧頂已經是該 Activity 了。則認為可以直接使用它,就不會再建立新的 Activity 例項了。

    因為不會建立新的 Activity 例項,所以 Activity 的生命週期就沒有什麼變化了。但是它的 onNewIntent 方法會被呼叫。

    singleTask 模式

    singleTop 很好的解決了重複建立棧頂 Activity 的問題。如果 Activity 沒有處於棧頂的位置,還是可能會建立多個 Activity 例項的。如何解決這種問題呢?那就需要藉助 singleTask 了。當 Activity 的啟動模式為 singleTask 的時候,每次啟動該 Activity 的時候系統會首先在返回棧中檢查是否存在該 Activity 的例項,如果發現已經存在則直接使用該例項。並把這個 Activity 之上的所有 Activity 全部出棧,如果沒有就會建立一個新的 Activity 例項。

    生命週期正常呼叫,onNewIntent 也會被呼叫。

    ingleInstance 模式

    singleInstance 模式的 Activity 會啟用一個新的返回棧來管理這個 Activity (其實如果 singleTask 模式指定了不同的 taskAffinity,也會啟動一個新的返回棧)。意義:假如我們的程式中有一個 Activity 是允許其他程式呼叫的,如果我們想實現其他程式和我們的程式可以共享這個 Activity 例項。那麼如何實現呢?假如使用前面 3 中啟動模式,肯定不行。因為,我們每個應用程式都有自己的返回棧,雖然是同樣這個 Activity,但是在不同的返回棧入棧的時候肯定是建立了新的例項了。而 singleInstance 可以解決這個問題,在這種模式下會有一個單獨的返回棧來管理這個 Activity,不管是那個應用程式來訪問這個 Activity,都共用的同一個返回棧,也就解決了共享 Activity 例項的問題。

    總結

    standard 和 singleTop 啟動模式都是在原任務棧中新建 Activity 例項,不會啟動新的 Task,即使你指定了 taskAffinity 屬性。

    什麼是 taskAffinity 屬性

    標識了一個 Activity 所需任務棧的名字,但不能根據這個名字來確定任務棧。因為你可以理解同樣一個任務棧有多個名字。預設情況下,所有 Activity 所需的任務棧的名字為應用的包名。可以單獨指定每一個 Activity 的 taskAffinity 屬性覆蓋預設值一個任務的 affinity 決定於這個任務的根 Activity 的 taskAffinity在概念上,具有相同的 affinity 的 activity (設定了相同 taskAffinity 屬性的 activity)屬於同一個任務。為一個 activity 的 taskAffinity 設定一個空字串,表明這個 Activity 不屬於任何 task

    taskAffinity 屬性不對 standard 和 singleTop 模式有任何影響 即使我們給這兩種模式設定了

    只是改變了 taskAffinity 的名字,但是任務棧依然還是啟動這個 Activity 的 Activity 所在的任務棧。

    singleTask 模式的 Activity 的啟動,啟動的時候會根據 taskAffinity 去尋找當前是否存在這麼一個任務棧,如果不存在就會建立一個新的任務棧,並建立新的 Activity 例項到進建立的任務棧中。如果存在,則查詢任務棧中是否有該 Activity 的例項。

    任務棧是可以跨程式的。

  • 中秋節和大豐收的關聯?
  • 益氣託毒湯裡都有哪些中藥?