Android 入門——Activity

Activity

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 的生命週期

先放上一張最經典的圖


Android 入門——Activity


  • 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 中通過 標籤指定 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 也會被調用。

singleInstance 模式

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 的實例。

任務棧是可以跨程序的。

參考:《第一行代碼》、https://blog.csdn.net/mynameishuangshuai/article/details/51491074


分享到:


相關文章: