Activity 總結

Activity 是 Android 四大組件之一,每一個 Activity 都會得到一個用於繪製其用戶界面的窗口,用戶可與其進行交互。如下來總結 Activity 的重點知識。android

生命週期

正常的生命週期分析

Activity生命週期的回調主要有 onCreate()onRestart()onStart()onResume()onPause()onStop()onDestory() 幾種方法,在生命週期裏有三個嵌套循環git

  • Activity 的整個生命週期發生在 onCreate()onDestroy() 之間,在 onCreate() 中執行「全局」狀態設置(例如狀態佈局),並在 onDestroy() 中釋放資源。
  • Activity 的可見生命週期發生在 onStart()onStop() 之間,在這段時間內Activity對用戶可見。能夠在這倆個方法之間保留向用戶顯示 Activity 所需的資源。在整個生命週期中,當 Activity 在對用戶可見和隱藏倆種狀態中交替變化時,系統會屢次調用 onStart()onStop()
  • Activity 的前臺生命週期發生在 onResume()onPause() 之間,Activity位於其餘 Activity 以前,可與用戶交互並具備輸入焦點。但狀態改變頻繁,建議作些輕量級操做。

生命週期

  • onCreate()首次建立 Activity 時調用。在這個方法裏執行全部正常的靜態設置-建立視圖、將數據綁定到列表等等。
  • onRestart()已中止並即將再次啓動前調用。
  • onStart()在 Activity 即將對用戶可見以前調用。若是 Activity 轉入前臺,則後接 onResume() ,若是 Activity 轉入隱藏狀態,則後接 onStop()
  • onResume()在 Activity 即將開始與用戶進行交互以前調用。此時,Activity 處於任務棧的頂層,並具備用戶輸入焦點。
  • onPause()當系統即將開始繼續另外一個 Activity 時調用。此方法一般用於確認對持久性數據的未保存更改,中止動畫以及其餘可能消耗CPU的內容。它應該迅速地執行所需操做,由於它返回後,下一個 Activity 才能繼續執行。若是 Activity 返回前臺,則後接 onResume() ,若是 Activity 轉入對用戶不可見狀態,則後接 onStop()
  • onStop()在 Activity 對用戶再也不可見時調用。若是 Activity 恢復與用戶的交互,則後接 onRestart() ,若是 Activity 被銷燬,則後接 onDestroy()
  • onDestroy()在 Activity 被銷燬前調用。當 Activity 由於被調用 finish() 或系統爲節省空間而暫時銷燬該 Activity 實例時,可能會調用它,能夠經過 isFinishing() 方法來區分。

圖中週期說明

  • 正常啓動一個 Activity ,回調以下:onCreate()->onStart()->onResume()
  • 當用戶打開新的 Activity 或切換到桌面時,回調以下:onPause()->onStop(),有一種特殊狀況:若是新的 Activity 採用了透明主題,那麼當前 Activity 不會回調 onStop()
  • 當用戶再次回到原 Activity 時,回調以下:onRestart()->onStart()->onResume()
  • 當用戶按back鍵回退時,回調以下:onPause()->onStop()->onDestroy()
  • 從整個生命週期來看,onCreate()onDestroy() 配對,只會調用一次。從 Activity 的可見狀態來講,onStart()onStop() 配對,會調用屢次。從 Activity 是否在前臺可交互來講, onResume()onPause() 配對,可調用屢次。

週期相關問題

onStart()onResume()onPause()onStop() 的區別?
  • onStart()onStop() 是從 Activity 是否可見來回調的,onResume()onPause() 是從 Activity 是否位於前臺來回調的。
倆個 Activity A 和 B,那麼 A 啓動 B 的過程當中,A 的 onPause() 與 B 的 onResume() 哪一個先執行?
  • 新 Activity 啓動以前,棧頂的 Activity 須要先 onPause() 後,新的 Activity 才能啓動的。

異常的生命週期分析

當 Activity 暫停或中止時,Activity 對象仍保留在內存中-有關其成員和當前狀態仍處於活動狀態。所以,用戶在 Activity 內所作的任何更改都會獲得保留,這樣一來,當 Activity 返回前臺時,這些更改仍然存在。
可是當資源相關的系統配置發生改變或系統內存不足時,Activity 對象可能會被銷燬,這時繼續 Activity 時根本沒法讓其狀態保持無缺,而是必須在用戶返回 Activity 時建立 Activity 對象,這些狀態信息會由 onSaveInstanceState() 來保存。github

數據恢復

  • 當 Activity 被異常終止後,系統會調用 onSaveInstanceState() 來保存當 Activity 的狀態。這個方法的調用時機是在 onStop() 以前,和 onPause() 沒有既定的時序關係。當 Activity 被從新建立後,系統會調用 onRestoreInstanceState() ,而且把 Activity 銷燬時經過 onSaveInstanceState() 保存的 Bundle 對象同時傳遞給 onRestoreInstanceState()onCreate() ,從時序上來講, onRestoreInstanceState()onStart() 以後。
  • 沒法保證系統會在銷燬 Activity 前調用 onSaveInstanceState() ,由於當正常離開當前頁面,顯示關閉 Activity 時,不須要保存狀態。並且在異常狀態下沒法肯定調用 onSaveInstanceState() 的時機,因此只用它來保存 Activity 的瞬間狀態,不要來保存持久性數據。
  • Activity 類的 onSaveInstanceState() 默認實現會恢復部分 Activity 狀態,具體地來講,默認實現會爲佈局中的每一個 View 調用相應的 onSaveInstanceState() 方法,讓每一個視圖都能提供有關自身的應保存信息。 Android 框架中幾乎每一個小部件都會根據須要實現此方法,以便在重建 Activity 時自動保存和恢復對UI所作的任何可見更改。咱們只須要爲保存其狀態的每一個小部件提供一個惟一的ID,若是小部件沒有ID,則系統沒法保存其狀態。
  • 系統配置發生改變後,Activity 會被從新建立,但咱們能夠指定 configChanges 屬性,不從新建立。好比不想讓屏幕旋轉時從新建立,給 configChanges 屬性添加 orientation 值,以下,android:configChanges="orientation"

任務和返回棧

  • 任務:在執行特定做業時與用戶交互的一系列 Activity。
  • 返回棧:這些 Activity 按照各自的打開順序排列在堆棧中。

當前 Activity 啓動另外一個 Activity 時,該新的 Activity 會被推送到堆棧頂部,成爲焦點所在。前一個 Activity 仍保留在堆棧中,可是處於中止狀態。當用戶按「返回」鍵時,當前 Activity 會從堆棧頂部彈出(被銷燬),而前一個 Activity 恢復執行。堆棧中的 Activity 永遠不會從新排列,僅推入和彈出堆棧,並按照「後進先出」對象結構運行。框架

啓動模式

定義 Activity 的新實例如何與當前任務關聯,來改變系統的默認行爲。ide

standard

默認模式。系統在每次啓動 一個Activity 都會從新建立一個新實例,無論這個實例是否已經存在。非 Activity 類型的 Context 沒有任務棧,用 getApplicationContext 直接啓動 Activity 會報錯,能夠加一個標誌位 FLAG_ACTIVITY_NEW_TASK ,實際以 singleTask 模式啓動的一個新的任務棧。佈局

singleTop

棧頂複用模式。若是新的 Activity 已經位於任務棧的棧頂,那麼此 Activity 不會被從新建立,同時經過 onNewIntent() 方法傳遞 Intent。若是新 Activity 的實例已經存在但不位於棧頂,那麼新的 Activity 仍然會被從新建立。動畫

singleTask

棧內複用模式。是一種單實例模式,在這種模式下,若是該 Activity 的一個實例已經存在於一個單獨的任務中,系統會經過調用現有實例的 onNewIntent() 方法向其傳送 Intent,而不是建立新實例。若是啓動的 Activity 位於當前任務棧中,啓動該 Activity 時,會把該 Activity 切換到棧頂後,還將致使它上邊的 Activity 所有出棧。若是啓動的 Activity 位於後臺任務棧中,則整個後臺任務棧會被切換到前臺。spa

singleInstance

單實例模式。是一種增強的 singleTask 模式。和 singleTask 相同,只是具備此種模式的 Activity 只能單獨位於一個任務棧中。code

使用

清單文件

在清單文件中聲明 Activity 時,使用 <activity> 元素的 lauchMode 屬性指定 Activity 應該如何與任務關聯。對象

Intent 標誌

啓動 Activity 時,經過 startActivity() 的 Intent 中加入相應的標誌,修改 Activity 與其任務的默認關聯方式。

  • FLAG_ACTIVITY_NEW_TASK:產生與 「singleTask」 模式相同的行爲。
  • FLAG_ACTIVITY_SINGLE_TOP:產生 「singleTop」 模式相同的行爲。
  • FLAG_ACTIVITY_CLEAR_TOP:若是正在啓動的 Activity 已在當前任務中運行,則會銷燬倩倩任務頂部的全部 Activity ,並經過 onNewIntent() 將此 Intent 傳遞給 Activity 已恢復的實例(如今位於頂部),而不是啓動該 Activity 的新實例。一般與 FLAG_ACTIVITY_NEW_TASK 結合使用,就會等同於「singleTask」 模式。
  • FLAG_ACTIVITY_EXCLUDE_RECENTS:具備這個標記的 Activity 不會出如今任務棧中,可用於不會經過歷史列表回到這個頁面的狀況,效果等同於 android:exludeFromRecents="true"

Intent 匹配規則

Intent 是一個消息傳遞對象,能夠向其餘應用組件發送請求操做。

Intent 類型

  • 顯示 Intent:按名稱(徹底限定類名)指定要啓動的組件。須要明確知道啓動對象的組件信息,包括包名和類名。
  • 隱式 Intent:不會指定特定的組件,而是聲明要執行的常規操做,從而容許其餘應用中的組件來處理它。建立隱式 Intent 時,Android 系統經過將 Intent 的內容與設備上其餘應用的清單文件中聲明的 intent-filter 進行比較,若 Intent 與 intent-filter 匹配,則系統內啓動該組件,如有多個匹配,則經過顯示的對話框來支持用戶選擇要使用的應用。

當一個 Intent 同時匹配 activity 聲明的任何一組 action,category 和 data 時,就可成功啓動對應的應用。

action

指定要執行的通用操做的字符串。Intent 中必須有一個 action ,且必須可以和過濾規則中的某個 action 相同便可匹配成功。

category

處理 Intent 組件類型的附加信息的字符串。若是 Intent 中含有 category,那麼全部的 category 都必須和過濾規則中的其中一個 category 相同。換句話說,Intent 裏的category 都必須是過濾規則中的 category。Intent 能夠沒有 category,由於系統會默認加上 android.intent.category.DEFAULT,這時對於接收的 activity ,就必須在 intent-filter 里加上這個默認的類別了。

data

引用待操做數據和/或該數據 MIME 類型的 URI ( Uri 對象)。data 由倆部分組成, mimeType 和 URI 。

  • mimeType:指媒體類型,好比 image/jpg、audio/mpeg4-generic 和 video/* 等。
  • URI :包含的數據比較多,具體結構: <scheme>://<host>:<port>[<path>|<pathPrefix>|<pathPattern>] ,Scheme 表示 URI 的模式,如 http,file,content 等。

能夠用 setData() 設置 URI,setType() 設置 MIME 類型,但同時使用時,請使用 setDataAndType() ,由於 調用 setData()setType() 會互相抵消彼此的值。匹配規則和 action 相似,它要求 Intent 中必須含有 data 數據,且 data 數據可以徹底匹配過濾規則中的某個 data 。

Extra

攜帶完成請求操做所需的附加信息的鍵值對。

Flag

Intent 的標誌,來指示 Android 系統如何啓動 Activity 以及啓動以後如何處理。

本文發表於我的博客:http://lavnfan.github.io/,歡迎指教。

相關文章
相關標籤/搜索