Android 入門--Activity

Activity 是什麼

簡單的來講,一個 Activity 包含了用戶能夠看到的界面,用來和用戶進行交互。一個應用程序中能夠有零個或者多個 Activity。零個 Activity 的話就是,這個程序不包含與用戶交互的界面。android

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

Android 是使用任務(Task)來管理 Activity 的。一個 Task 就是一組存放在棧裏的 Activity 的集合。這個任務也被稱爲返回棧(Back Stack),棧是一種先進先出的數據結構,默認狀況下,每當咱們啓動了一個新的 Activity,它會被加入到棧中,並處於棧頂的位置,當 Activity 的 finish 方法去銷燬一個 Activity 的時候,這個 Activity 就會出棧。系統老是會顯示處於棧頂的 Activity 給用戶。數據結構

Activity 的狀態

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

  • 運行狀態spa

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

  • 暫停狀態3d

    當一個 Activity 再也不處於棧頂位置,可是仍然可見的時候,這種狀況下這個 Activity 就處於暫停狀態。Activity 不在棧頂了居然還能被看到?你想若是棧頂的 Activity 是一個對話框或者是透明的狀況下,是否是這個不在棧頂位置的 Activity 依然能夠被用戶看到啊。這種狀態的 Activity,系統也是不肯意去回收的。code

  • 中止狀態cdn

    當一個 Activity 再也不處於棧頂位置,並且徹底看不到的時候,就進入了中止狀態了。系統仍然會爲這樣的 Activity 保留響應的狀態和成員變量,但這並非徹底可靠的,當內存緊張的時候,處於中止狀態的 Activity 有可能被系統回收。xml

  • 銷燬狀態blog

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

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 中經過 <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 也會被調用。

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 模式有任何影響 即便咱們給這兩種模式設置了

<activity android:name=".ActivityStandard" android:launchMode="standard" android:taskAffinity="com.syd"/>
複製代碼

只是改變了 taskAffinity 的名字,可是任務棧依然仍是啓動這個 Activity 的 Activity 所在的任務棧。

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

任務棧是能夠跨程序的。

參考:《第一行代碼》、blog.csdn.net/mynameishua…

相關文章
相關標籤/搜索