導航:首頁 > 操作系統 > androidactivity棧管理

androidactivity棧管理

發布時間:2023-03-24 10:54:36

android採用什麼方式管理activity實例

Android採用任務線(Task)的方式來管理Activity的實例搭模。


在開發Android應用時,經常會涉及一些消耗大量系統內存的情況,例如視頻播放、大量圖片或者程序中開啟多個Activity沒有及時關閉等,會導致程序出現錯誤。為了避免這種問題,Google提供了一套完整的機制讓開發人員控制 Android中的任務線。

Android系統中的任務線,類似於一個容器,用於管理所有的Activity實例。在存放Activity時,滿足「先進後出 (First-In/Last-Out )"的原則。

但是使用任務線有以下缺點:粗枝鏈

每開啟一次頁面都會在任務棧中添加一個岩孫Activity,而只有任務棧中的Activity全部清除出線時,任務線被銷毀,程序才會退出。這樣就造成了用戶體驗差, 需要點擊多次返回才可以把程序退出。

每開啟一次頁面都會在任務棧中添加一個Activity還會造成數據冗餘, 重復數據太多, 會導致內存溢出的問題(OOM)。為了解決任務棧產生的問題,Android為Activity設計了啟動模式。

在實際開發中,應根據特定的需求為每個Activity指定恰當的啟動模式。Activity的啟動模式有4種,分別是standard、singleTop、singleTask和singlelnstance。在AndroidManifest.xml中,通過<activity>標簽的android:launchMode屬性可以設置啟動模式。

Ⅱ 全面解析Activity: Activity的工作過程

本文將對Activity的工作過程進行分析。

主要學習以下內容:

(1)系統內部是如何啟動一個Activity的?

(2)新Activity的對象是何時創建的?

(3)Activity的各個生命周日是被系統何時回調的?

Activity啟動流程分兩種,一種是啟動正在運行的app的Activity,即啟動子Activity。如無特殊聲明默認和啟動該activity的activity處於同一進程。如果有聲明在一個新的進程中,則處於兩個進程。另一種是打開新的app,即為Launcher啟動新的Activity。後邊啟動Activity的流程是一樣的,區別是前邊判斷進程是否存在的那部分。

Activity的啟動流程整體如下:

一.Activity啟動階段

(一)涉及到的概念

進程:Android系統為每個APP分配至少一個進程

IPC:跨進程通信,Android中採用Binder機制。

(二)涉及到的類

ActivityStack:Activity在AMS的棧管理,用來記錄已經啟動的Activity的先後關系,狀態信息等。通過ActivityStack決定是否需要啟動新的進程。

ActivitySupervisor:管理 activity 任務棧

ActivityThread:ActivityThread 運行在UI線程(主線程),App的真正入口。

ApplicationThread:用來實現AMS和ActivityThread之間的交互。

ApplicationThreadProxy:ApplicationThread 在服務端的代理。AMS就是通過該代理與ActivityThread進行通信的。

IActivityManager:繼承與IInterface介面,抽象出跨進程通信需要實現的功能

AMN:運行在server端(SystemServer進程)。實現了Binder類,具體功能由子類AMS實現。

AMS:AMN的子類,負責管理四大組件和進程,包括生命周期和狀態切換。AMS因為要和ui交互,所以極其復雜,涉及window。

AMP:AMS的client端代理(app進程)。了解Binder知識可以比較容易理解server端的stub和client端的proxy。AMP和AMS通過Binder通信。

Instrumentation:儀表盤,負責調用Activity和Application生命周期。測試用到這個類比較多。

(三)涉及到的進程

(1)Launcher所在的進程

(2)AMS所在的SystemServer進程

(3)要啟動的Activity所在的app進程

如果是啟動根Activity,就涉及上述三個進程。

如果是啟動子Activity,那麼就只涉及AMS進程和app所在進程。

(四)具體流程

Launcher:Launcher通知AMS要啟動activity。

startActivitySafely->startActivity->Instrumentation.execStartActivity()(AMP.startActivity)->AMS.startActivity

AMS:PMS的resoveIntent驗證要啟動activity是否匹配。如果匹配,通過ApplicationThread發消息給Launcher所在的主線程,暫停當前Activity(即Launcher)。

暫停完,在該activity還不可見時,通知AMS,根據要啟動的Activity配置ActivityStack。然後判斷要啟動的Activity進程是否存在?

存在:發送消息LAUNCH_ACTIVITY給需要啟動的Activity主線程,執行handleLaunchActivity

不存在:通過socket向zygote請求創建進程。進程啟動後,ActivityThread.attach

判斷Application是否存在,若不存在,通過LoadApk.makeApplication創建一個。在主線程中通過thread.attach方法來關聯ApplicationThread。

在通過ActivityStackSupervisor來獲取當前需要顯示的ActivityStack。

繼續通過ApplicationThread來發送消息給主線程的Handler來啟動Activity (handleLaunchActivity)。

handleLauchActivity:調用了performLauchActivity,里邊Instrumentation生成了新的activity對象,繼續調用activity生命周期。

IPC過程:

雙方都是通過對方的代理對象來進行通信。

1.app和AMS通信:app通過本進程的AMP和AMS進行Binder通信

2.AMS和新app通信:通過ApplicationThreadProxy來通信,並不直接和ActivityThread通信

(五)參考函數流程

Activity啟動流程(從Launcher開始):

第一階段: Launcher通知AMS要啟動新的Activity(在Launcher所在的進程執行)

第二階段:AMS先校驗一下Activity的正確性,如果正確的話,會暫存一下Activity的信息。然後,AMS會通知Launcher程序pause Activity(在AMS所在進程執行)

第三階段:pause Launcher的Activity,並通知AMS已經paused(在Launcher所在進程執行)

第四階段:檢查activity所在進程是否存在,如果存在,就直接通知這個進程,在該進程中啟動Activity;不存在的話,會調用Process.start創建一個新進程(執行在AMS進程)

第五階段: 創建ActivityThread實例,執行一些初始化操作,並綁定Application。如果Application不存在,會調用LoadedApk.makeApplication創建一個新的Application對象。之後進入Loop循環。(執行在新創建的app進程)

第六階段:處理新的應用進程發出的創建進程完成的通信請求,並通知新應用程序進程啟動目標Activity組件(執行在AMS進程)

第七階段: 載入MainActivity類,調用onCreate聲明周期方法(執行在新啟動的app進程)

從另一個角度下圖來概括:

下面簡要介紹一下啟動的過程:

        Step 1. 無論是通過Launcher來啟動Activity,還是通過Activity內部調用startActivity介面來啟動新的Activity,都通過Binder進程間通信進入到ActivityManagerService進程中,並且調用ActivityManagerService.startActivity介面; 

        Step 2. ActivityManagerService調用ActivityStack.startActivityMayWait來做准備要啟動的Activity的相關信息;

        Step 3. ActivityStack通知ApplicationThread要進行Activity啟動調度了,這里的ApplicationThread代表的是調用ActivityManagerService.startActivity介面的進程,對於通過點擊應用程序圖標的情景來說,這個進程就是Launcher了,而對於通過在Activity內部調用startActivity的情景來說,這個進程就是這個Activity所在的進程了;

        Step 4. ApplicationThread不執行真正的啟動操作,它通過調用ActivityManagerService.activityPaused介面進入到ActivityManagerService進程中,看看是否需要創建新的進程來啟動Activity;

        Step 5. 對於通過點擊應用程序圖標來啟動Activity的情景來說,ActivityManagerService在這一步中,會調用startProcessLocked來創建一個新的進程,而對於通過在Activity內部調用startActivity來啟動新的Activity來說,這一步是不需要執行的,因為新的Activity就在原來的Activity所在的進程中進行啟動;

        Step 6. ActivityManagerServic調用ApplicationThread.scheleLaunchActivity介面,通知相應的進程執行啟動Activity的操作;

        Step 7. ApplicationThread把這個啟動Activity的操作轉發給ActivityThread,ActivityThread通過ClassLoader導入相應的Activity類,然後把它啟動起來。

Ⅲ activity(Android組件中最重要的四大組件之一)詳細資料大全

activity是Android組件中最基本也是最為常見用的四大組件之一。Android四大組件有Activity,Service服務,Content Provider內容提供,BroadcastReceiver廣播接收器。

基本介紹

概要說明,詳細說明,基本狀態,狀態轉換,方法通知,

概要說明

Activity是Android組件中最基本也是最為常見用的四大組件(Activity,Service服務,Content Provider內容提供者,備頌孫BroadcastReceiver廣播接收器)之一。 Activity是一個應用程式組件,提供一個螢幕,用戶可以用來互動為了完成某項任務。 Activity中所有操作都與用戶密切相關,是一個負責與 用戶互動 的組件,可以通過setContentView(View)來 顯示指定控制項 。 在一個android套用中,一個Activity通常就是一個單獨的螢幕,它上面可以顯示一些控制項也可以監聽並處理用戶的事件做出回響。Activity之間通過Intent進行通信。

詳細說明

基本狀態

在android 中,Activity 擁有四種基本狀態:
  1. Active/Running
一個新 Activity 啟動入棧後,它顯示在螢幕最前端,處理是處於棧的最頂端(Activity棧頂),此時它處於可見並可和用戶互動的激活狀態,叫做活動狀態或者運行狀態(active or running)。 2 . Paused 當 Activity失去焦點, 被一個新的非全螢幕的Activity 或者一個透明的Activity 被放置在棧頂,此時的狀態叫做暫停狀態(Paused)。此時它依然與視窗管理器保持連線,Activity依然保持活力(保持所有的狀態,成員信息,和視窗管理器保持連線)櫻空,但是在系統記憶體極端低下的時候將被強行終止掉。所以它仍然仿鏈可見,但已經失去了焦點故不可與用戶進行互動。 3 . Sped 如果一個Activity被另外的Activity完全覆蓋掉,叫做停止狀態(Sped)。它依然保持所有狀態和成員信息,但是它不再可見,所以它的視窗被隱藏,當系統記憶體需要被用在其他地方的時候,Sped的Activity將被強行終止掉。 4 . Killed 如果一個Activity是Paused或者Sped狀態,系統可以將該Activity從記憶體中刪除,Android系統採用兩種方式進行刪除,要麼要求該Activity結束,要麼直接終止它的進程。當該Activity再次顯示給用戶時,它必須重新開始和重置前面的狀態。

狀態轉換

當一個 Activity 實例被創建、銷毀或者啟動另外一個 Activity 時,它在這四種狀態之間進行轉換,這種轉換的發生依賴於用戶程式的動作。下圖說明了 Activity 在不同狀態間轉換的時機和條件: 圖1. Activity 的狀 態轉換 如上所示,Android 程式設計師可以決定一個 Activity 的「生」,但不能決定它的「死」,也就是說程式設計師可以啟動一個 Activity,但是卻不能手動的「結束」一個 Activity。當你調用 Activity.finish() 方法時,結果和用戶按下 BACK 鍵一樣:告訴 Activity Manager 該 Activity 實例完成了相應的工作,可以被「回收」。隨後 Activity Manager 激活處於棧第二層的 Activity 並重新入棧,同時原 Activity 被壓入到棧的第二層,從 Active 狀態轉到 Paused 狀態。例如:從 Activity1 中啟動了 Activity2,則當前處於棧頂端的是 Activity2,第二層是 Activity1,當我們調用 Activity2.finish() 方法時,Activity Manager 重新激活 Activity1 並入棧,Activity2 從 Active 狀態轉換 Sed 狀態, Activity1. onActivityResult(int requestCode, int resultCode, Intent data) 方法被執行,Activity2 返回的數據通過 data 參數返回給 Activity1。 Activity棧 Android 是通過一種 Activity 棧的方式來管理 Activity 的,一個 Activity 的實例的狀態決定它在棧中的位置。處於前台的 Activity 總是在棧的頂端,當前台的 Activity 因為異常或其它原因被銷毀時,處於棧第二層的 Activity 將被激活,上浮到棧頂。當新的 Activity 啟動入棧時,原 Activity 會被壓入到棧的第二層。一個 Activity 在棧中的位置變化反映了它在不同狀態間的轉換。Activity 的狀態與它在棧中的位置關系如下圖所示: 圖2. Activity 的狀 與它在 中的位置 如上所示,除了最頂層即處在 Active 狀態的 Activity 外,其它的 Activity 都有可能在系統記憶體不足時被回收,一個 Activity 的實例越是處在棧的底層,它被系統回收的可能性越大。系統負責管理棧中 Activity 的實例,它根據 Activity 所處的狀態來改變其在棧中的位置。

方法通知

下面的圖顯示了Activity的重要狀態轉換,矩形框表明Activity在狀態轉換之間的回調介面,開發人員可以重載實現以便執行相關代碼,帶有顏色的橢圓形表明Activity所處的狀態。 3 . Activity 的狀 轉換的方法和實現 在上圖中,Activity有三個關鍵的循環: 1. 整個的生命周期,從onCreate(Bundle)開始到onDestroy()結束。Activity在onCreate()設定所有的「全局」狀態,在onDestory()釋放所有的資源。例如:某個Activity有一個在後台運行的執行緒,用於從網路下載數據,則該Activity可以在onCreate()中創建執行緒,在onDestory()中停止執行緒。 2. 可見的生命周期,從onStart()開始到onS()結束。在這段時間,可以看到Activity在螢幕上,盡管有可能不在前台,不能和用戶互動。在這兩個介面之間,需要保持顯示給用戶的UI數據和資源等,例如:可以在onStart中注冊一個IntentReceiver來監聽數據變化導致UI的變動,當不再需要顯示時候,可以在onS()中注銷它。onStart(),onS()都可以被多次調用,因為Activity隨時可以在可見和隱藏之間轉換。 3. 前台的生命周期,從onResume()開始到onPause()結束。在這段時間里,該Activity處於所有 Activity的最前面,和用戶進行互動。Activity可以經常性地在resumed和paused狀態之間切換,例如:當設備准備休眠時,當一個 Activity處理結果被分發時,當一個新的Intent被分發時。所以在這些介面方法中的代碼應該屬於非常輕量級的。

Ⅳ Android中的Activity詳解--啟動模式與任務棧

目錄

activity的簡單介紹就不寫了,作為最常用的四大組件之一,肯定都很熟悉其基本用法了。

首先,是都很熟悉的一張圖,即官方介紹的Activity生命周期圖.

情景:打開某個應用的的FirstActivity調用方法如下:
由於之前已經很熟悉了,這里就簡單貼一些圖。

按下返回鍵:

重新打開並按下home鍵:

再重新打開:

在其中打開一個DialogActivity(SecondActivity)

按下返回:

修改SecondAcitvity為普通Activity,依舊是上述操作:

這里強調一下 onSaveInstanceState(Bundle outState) 方法的調用時機:
當Activity有可能被系統殺掉時調用,注意,一定是被系統殺掉,自己調用finish是不行的。
測試如下:FirstActivity啟動SecondActivity:

一個App會包含很多個Activity,多個Activity之間通過intent進行跳轉,那麼原始的Activity就是使用棧這個數據結構來保存的。
Task
A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack (the back stack ), in the order in which each activity is opened.
即若干個Activity的集合的棧表示一個Task。
當App啟動時如果不存在當前App的任務棧就會自動創建一個,默認情況下一個App中的所有Activity都是放在一個Task中的,但是如果指定了特殊的啟動模式,那麼就會出現同一個App的Activity出現在不同的任務棧中的情況,即會有任務棧中包含來自於不同App的Activity。

標准模式,在不指定啟動模式的情況下都是以此種方式啟動的。每次啟動都會創建一個新的Activity實例,覆蓋在原有的Activity上,原有的Activity入棧。
測試如下:在FirstActivity中啟動FirstActivity:

當只有一個FirstActivity時堆棧情況:

此種模式下,Activity在啟動時會進行判斷,如果當前的App的棧頂的Activity即正在活動的Activity就是將要啟動的Activity,那麼就不會創建新的實例,直接使用棧頂的實例。
測試,設置FirstActivity為此啟動模式,多次點擊FirstActivity中的啟動FirstActivity的按鈕查看堆棧情況:
(其實點擊按鈕沒有啟動新Activity的動畫就可以看出並沒有啟動新Activity)

大意就是:
對於使用singleTop啟動或Intent.FLAG_ACTIVITY_SINGLE_TOP啟動的Activity,當該Activity被重復啟動(注意一定是re-launched,第一次啟動時不會調用)時就會調用此方法。
且調用此方法之前會先暫停Activity也就是先調用onPause方法。
而且,即使是在新的調用產生後此方法被調用,但是通過getIntent方法獲取到的依舊是以前的Intent,可以通過setIntent方法設置新的Intent。
方法參數就是新傳遞的Intent.

1.如果是同一個App中啟動某個設置了此模式的Activity的話,如果棧中已經存在該Activity的實例,那麼就會將該Activity上面的Activity清空,並將此實例放在棧頂。
測試:SecondActivity啟動模式設為singleTask,啟動三個Activity:

這個模式就很好記,以此模式啟動的Activity會存放在一個單獨的任務棧中,且只會有一個實例。
測試:SecondActivity啟動模式設為singleInstance

結果:

顯然,啟動了兩次ThirdActivity任務棧中就有兩個實例,而SecondActivity在另外一個任務棧中,且只有一個。

在使用Intent啟動一個Activity時可以設置啟動該Activity的啟動模式:
這個屬性有很多,大致列出幾個:

每個啟動的Activity都在一個新的任務棧中

singleTop

singleTask

用此種方式啟動的Activity,在它啟動了其他Activity後,會自動finish.

官方文檔介紹如下:

這樣看來的話,通俗易懂的講,就是給每一個任務棧起個名,給每個Activity也起個名,在Activity以singleTask模式啟動時,就檢查有沒有跟此Activity的名相同的任務棧,有的話就將其加入其中。沒有的話就按照這個Activity的名創建一個任務棧。
測試:在App1中設置SecondActivity的taskAffinity為「gsq.test」,App2中的ActivityX的taskAffinity也設為「gsq.test」

任務棧信息如下:

結果很顯然了。
測試:在上述基礎上,在ActivityX中進行跳轉到ActivityY,ActivityY不指定啟動模式和taskAffinity。結果如下:

這樣就沒問題了,ActivityY在一個新的任務棧中,名稱為包名。
這時從ActivityY跳轉到SecondActivity,那應該是gsq.test任務棧只有SecondActivity,ActivityX已經沒有了。因為其啟動模式是singleTask,在啟動它時發現已經有一個實例存在,就把它所在的任務棧上面的Activity都清空了並將其置於棧頂。

還有一點需要提一下,在上面,FirstActivity是App1的lunch Activity,但是由於SecondActivity並沒有指定MAIN和LAUNCHER過濾器,故在FirstActivity跳轉到SecondActivity時,按下home鍵,再點開App1,回到的是FirstActivity。

大致就先寫這么多吧,好像有點長,廢話有點多,估計也有錯別字,不要太在意~~~

Ⅳ Android Activity生命周期解析

Activity 用戶可以做單一的、集中的事情。幾乎所有的Activity都與用戶進行交互,所以Activity類負責創建一個窗口,你可以通過調用setContentView(View)把你的UI布局放置在Activity的窗口中。作為四大組件之一,使用頻率非常高。深入了解Activity,對於我們高質量開發是很有幫助的,下面我們就來看看Activity的生命周期。

Android系統中是通過Activity棧的方式來管理Activity的,而Activity自身則是通過生命周期的方法來管理的自己的創建與銷毀。那麼我們就來看看Activity生命周期是怎樣運作的。

周期即活動從開始到結束所經歷的各種狀態。生命周期即活動從開始到結束所經歷的各個狀態。從一個狀態到另一個狀態的轉變,從無到有再到無,這樣一個過程中所經歷的狀態就叫做生命周期。

Acitivity本質上有四種狀態:

在上面的四中常有的狀態之間,還有著其他的生命周期來作為不同狀態之間的過度,用於在不同的狀態之間進行轉換。

我們先來看看下面這張經典的生命周期流程圖:

1)啟動Activity
onCreate() —> onStart() —> onResume()
2)按Home鍵回到桌面 / 鎖屏
onPause() —> onStop()
3)從桌面回到Activity / 解鎖
onRestart() —> onStart() —> onResume()
4)跳轉新Activity
A: onPause() —> onStop()
B: onCreate() —> onStart() —> onResume()
A —> B: onPause()_A —> onCreate()_B —> onStart()_B —> onResume()_B —> onStop()_A
5)返回上一個Activity
B: onPause() —> onStop() —> onDestroy()
A: onRestart() —> onStart() —> onResume()
B —> A: onPause()_B —> onRestart()_A —> onStart()_A —> onResume()_A —> onStop()_B —> onDestroy()_B
6)退出Activity
onPause() —> onStop() —> onDestroy()

Activity官方文檔,開啟傳送門

至此Activity的整個生命周期都介紹完了,現在我們再看之前的生命周期流程圖,是不是清晰許多。搞清楚Activity活動原理,這樣理解起來就會容易許多,工作中也能如魚得水。

Ⅵ Android Activity啟動模式與狀態保存及恢復詳解

       Activity是 Android組件 中最基本也是最為常見用的四大組件(Activity,Service服務,Content Provider內容提供者,BroadcastReceiver廣播接收器)之一 。
       Activity是一個應用程序 組件 ,提供一個 屏幕 ,用戶可以用來交互為了完成某項任務。
       Activity中所有操作都與用戶密切相關,是一個負責與 用戶交互 的組件,可以通過setContentView(View)來 顯示指定控制項
       在一個android應用中,一個Activity通常就是一個單獨的屏幕,它上面可以顯示一些控制項也可以監聽並處理用戶的事件做出響應。Activity之間通過Intent進行通信。
       關於Activity啟動流程請參考之前的文章 Android activity啟動流程分析

       activity有四種啟動模式,分別為standard,singleTop,singleTask,singleInstance。如果要使用這四種啟動模式,必須在manifest文件中<activity>標簽中的launchMode屬性中配置。

       標準的默認啟動模式,這種模式下activity可以被多次實例化,即在一個task中可以存在多個activity,每一個activity會處理一個intent對象,(在A中再次啟動A,會存在後面的A在前面的A上面,當前task會存在兩個activity的實例對象)

       如果一個singleTop模式啟動的activity實例已經存在於棧頂,那麼再次啟動這個activity的時候,不會重新創建實例,而是重用位於棧頂的那個實例,並且會調用實例的onNewIntent()方法將Intent對象傳遞到這個實例中,如果實例不位於棧頂,會創建新的實例。

       啟動模式設置為singleTask,framework在啟動該activity時只會把它標示為可在一個新任務中啟動,至於是否在一個新任務中啟動,還要受其他條件的限制,即taskAffinity屬性。
        taskAffinity :默認情況下,一個應用中的所有activity具有相同的taskAffinity,即應用程序的包名。我們可以通過設置不同的taskAffinity屬性給應用中的activity分組,也可以把不同的應用中的activity的taskAffinity設置成相同的值,當兩個不同應用中的activity設置成相同的taskAffinity時,則兩個activity會屬於同一個TaskRecord。
       在啟動一個singleTask的Activity實例時,如果系統中已經存在這樣一個實例,就會將這個實例調度到任務棧的棧頂,並清除它當前所在任務中位於它上面的所有的activity;如果這個已存在的任務中不存在一個要啟動的Activity的實例,則在這個任務的頂端啟動一個實例;若這個任務不存在,則會啟動一個新的任務,在這個新的任務中啟動這個singleTask模式的Activity的一個實例。

       以singleInstance模式啟動的Activity具有全局唯一性,即整個系統中只會存在一個這樣的實例,如果在啟動這樣的Activiyt時,已經存在了一個實例,那麼會把它所在的任務調度到前台,重用這個實例。
       以singleInstance模式啟動的Activity具有獨占性,即它會獨自佔用一個任務,被他開啟的任何activity都會運行在其他任務中(官方文檔上的描述為,singleInstance模式的Activity不允許其他Activity和它共存在一個任務中)。
       被singleInstance模式的Activity開啟的其他activity,能夠開啟一個新任務,但不一定開啟新的任務,也可能在已有的一個任務中開啟,受條件的限制,這個條件是:當前系統中是不是已經有了一個activity B的taskAffinity屬性指定的任務。

       涉及到Activity啟動,就不得不說一下Activity的管理,Activity是以什麼方式及被什麼類來進行管理的,涉及的類主要如下:

       歷史棧中的一個條目,代表一個activity。ActivityRecord中的成員變數task表示其所在的TaskRecord,ActivityRecord與TaskRecord建立了聯系。

       內部維護一個 ArrayList<ActivityRecord> 用來保存ActivityRecord,TaskRecord中的mStack表示其所在的ActivityStack,TaskRecord與ActivityStack建立了聯系。

       內部維護了一個 ArrayList<TaskRecord> ,用來管理TaskRecord,ActivityStack中持有ActivityStackSupervisor對象,由ActivityStackSupervisor創建。

       負責所有ActivityStack的管理。內部管理了mHomeStack、mFocusedStack和mLastFocusedStack三個Activity棧。其中,mHomeStack管理的是Launcher相關的Activity棧;mFocusedStack管理的是當前顯示在前台Activity的Activity棧;mLastFocusedStack管理的是上一次顯示在前台Activity的Activity棧。

       ActivityThread 運行在UI線程(主線程),App的真正入口。

       用來實現AMS和ActivityThread之間的交互。

       負責調用Activity和Application生命周期。

       當一個Activity未被主動關閉,即「被動關閉」時,可能需要系統給用戶提供保持一些狀態的入口。

       前面說的入口就是:Activity提供了onSaveInstanceState()方法,該方法是Activity在關閉前保存狀態的核心方法。

       前面提到「被動關閉」,如果是主動關閉那麼就不會調用,比如:按back鍵、調用finish()等,那麼"被動關閉"的場景有哪些呢?下面給列舉一下:

       肯定在調用onStop()前被調用,但不保證在onPause()前 / 後,一般是在onPause()後調用。

       當需要保持狀態時,在onSaveInstanceState()內執行以下邏輯:

       當需要恢復時,在onCreate()內部執行以下邏輯:

       布局每個View默認實現:onSaveInstanceState(),即UI的任何改變都會自動的存儲和在activity重新創建的時候自動的恢復(只有在為該UI提供了唯一ID後才起作用);
       若需復寫該方法從而存儲額外的狀態信息時,應先調用父類的onSaveInstanceState()(因為默認的onSaveInstanceState()幫助UI存儲它的狀態);
       只使用該方法記錄Activity的瞬間狀態(UI的狀態),而不是去存儲持久化數據,因為onSaveInstanceState()調用時機不確定性;可使用 onPause()[一定會執行]存儲持久化數據;

       Activity提供了onRestoreInstanceState()方法,該方法是Activity在重新創建後恢復之前保存狀態的核心方法。

       若被動關閉了Activity,即調用了onSaveInstanceState(),那麼下次啟動時會調用onRestoreInstanceState()。

       onCreate()--->onStart()--->onRestoreInstanceState()--->onResume()

        注意: onSaveInstanceState()、onRestoreInstanceState()不一定 成對被調用
       如:當正在顯示Activity A時,用戶按下HOME鍵回到主界面,然後用戶緊接著又返回到Activity A,此時Activity A一般不會因為內存的原因被系統銷毀,故Activity A的onRestoreInstanceState()不會被執行;
       針對以上情況,onSaveInstanceState保持的參數可以選擇在onCreate()內部進行解析使用,因為onSaveInstanceState的bundle參數會傳遞到onCreate方法中,可選擇在onCreate()中做數據還原。
        至此:Activity的啟動模式及Activity的狀態保持及恢復介紹完畢。

Ⅶ Activity的基礎知識(下)

上篇總結了Activity的一些知識,現在繼續對Activity的知識進行梳理,包括Activity直接傳遞數據,Activity的生命周期,Activity的啟動模式等.
1.intent傳遞數據:
使用startActivity方法,intent的putExtra()方法,以鍵值對的形式傳遞數據,該方法有很多重載方法,可以根據傳遞數據的不同類型選擇合適的方法.除了有putExtra()方法外,還有putExtras()方法,傳遞的參數是Bundle.

如果傳遞的是對象,這個對象要實現序列化,也就是實現Parcelable或者Serializable介面.
如果希望被啟動的頁面返回數據,需要使用startActivityForResult()方法,這個方法中需要設置訪問號,用來區分不同的訪問者.並且在啟動頁重寫onActivityResult方法用來接收返回的數據,

2.兩種情況下的Activity的生命周期.
正常情況下的生命周州春或期,正常情況是指用戶的正常操作下的Activity的生命周期.後面會分析異常情況下的生命周期.
onCreate: Activity第一次創建時候的回調,主要是在這個方法進行初始化工作,比如初始化控制項和事件綁定工作.
onStart:Activity從不可見狀態變成可見狀態.
onResume:Activity變成前台,可以和用戶交互.
onPause:Activity可見但是不能和用戶交互.
onStop:Activity從可見變得不可見,成為後台Activity.
onDestroy:Activity銷毀時調用.
onRestart:Activity從後台冊伍變成前台Activity.
在啟動Activity和兩個Activity之間跳轉時,可以知道Activity的生命周期變化過程,有兩個說明:(1)在兩個Activity跳轉時,第一個Activty的onPause,onStop方法和第二個Activity的生命周期方法調用時機.

第一個Activity先執行onPause方法,第二個Activity才能創建.這也就意味著在onPause方法中不能執行太耗時的操作,否則會影響第二個Activity的創建.在源碼(ActivityStack)中有這樣的注釋:

(2)onStart和onResume,onPause和onStop這兩對方法的實質不同處:onStart和onStop這兩個方法是從Activity的可見性來區分的,onResume和onPause是從Activity是否處於前台,是否可以和用戶交互來區分的,注意在onPause調用時Activity還是可見的,調用時機比如彈出dialog時,下面的Activity是可見的.這個時候調用的是onPause方法.
異常情況下Activity的生命周期:異常情況下是指資源相關配置發生變化或後台Activity被系統回收時Activity的生命周森茄期.後台Activity被系統回收的情況比較難復現,在資源相關配置發生變化時和後台Activity被回收時的生命周期執行過程是一樣的,比較容易復現的就是橫豎屏切換時的生命周期執行過程.在 AndroidManifest的Activity組件下配置android:screenOrientation標簽,當設置可以橫豎方向隨著方向感應器來調節時,在切換時會出現先銷毀Activity再創建的過程.
過程:

在這種情況下有可能會有數據的丟失,系統提供用來保存數據和還原數據的方法:onSaveInstanceState和onRestoreInstanceState.用方法參數Bundle可以保存和還原數據.

可以根據需要設置android:screenOrientation標簽,設定activity的方向,如果activity的方向是需要橫豎屏切換,但是不容許銷毀Activity,可以設置如下標簽,當這些情況(常用的)發生變化是不會重新走Activity的生命周期方法,只會調用onConfigurationChanged,可以根據情況在這個方法里更新操作.

切換時的log輸出

3.Activity的四種啟動模式
標准:是Activity的默認啟動模式,對於AndroidManifest的Activity節點下的android:launchMode="standard"標簽.
特定:每次啟動都會重新創建新的Activity.
singleTop:對應的AndroidManifes的Activity節點下的android:launchMode="singleTop"標簽
特點:當此模式的Activity處於棧頂時,不會重新創建新的Activity,會調用onNewIntent方法,如果更新Activity的intent,需要調用 setIntent()方法,具體的生命周期過程

singleTask:在activity棧中已經有需要再啟動的activity時,會先清除位於需要啟動activity之上的activity,例如:啟動順序mainActivity-activityA -activityB-activityA,其中activityA是singleTask的啟動模式:

singleInstance:在一個棧中單獨存在的activity.
關於activity棧:是指用來管理activity一種"先進先出"的隊列結構,查看activity對應棧的方法:Activity的getTaskId()方法,同一個棧的id值是相同的.adb shell mpsys activity在終端查看棧結構,比如還是上面的activity啟動順序,不同是ActivityA這是設置成singleInstance,這是的棧結構:有兩個TaskRecord,其中ActivityB和MainActivity位於同一個棧中.

4.Activity開發中使用技巧:
<1>定義一個父Activity,在創建新的Activity時繼承這個activity即可,將一些activity的公共設置可以設置在父activity中,比如獲取每個Activity的名字,設置activity的窗體屬性,同一管理activity的生命周期等,
<2>在啟動的activity中定義靜態方法,啟動條件會顯而易見:

<3>管理activity類,用來一鍵退出app.在父類Activity的創建和銷毀時用來添加和移除Activity,在需要一鍵退出的地方調用靜態finishAllActivity方法.

Ⅷ Android之Activity全面解析,有些知識點容易忘記

Activity作為安卓四大組件之一,是最重要也是用得最多的組件,涉及的知識點非常多,有些知識點平時開發很少用到,但在某些場景下需要特別注意,本文詳細整理了Activity涉及的知識點,供開發參考。

針對Activity可以提出很多問題,如:
Activity 的生命周期?
Activity 之間的通信方式?
Activity 各種情況下的生命周期?
橫豎屏切換時 Activity 的生命周期?
前台切換到後台,然後再回到前台時 Activity 的生命周期?
彈出 Dialog 的時候按 Home 鍵時 Activity 的生命周期?
兩個Activity之間跳轉時的生命周期?
下拉狀態欄時 Activity 的生命周期?
Activity 與 Fragment 之間生命周期比較?
Activity 的四種 LaunchMode(啟動模式)的區別?
Activity 狀態保存與恢復?
Activity的轉場動畫有哪些實現方式?
Activity的生命周期中怎麼獲取控制項寬高?
onNewIntent的執行時機?
如何連續退出多個Activity?

如何把Acitivty設置成Dialog樣式 ,android:theme="@android:style/Theme.Dialog"

關於橫豎屏切換的生命周期,對應不同的手機,由於廠商定製的原因,會有不同的效果,如設置了configChanges="orientation」在有些手機會執行各個生命周期,但有些手機卻不會執行。
網上常見的結論如下:

但實際的測試如下:

可以看出,不同廠商的手機切屏生命周期會有差異。
從API 13以上,當設備在橫豎切屏時,「屏幕尺寸」也會發生變化,因此為了杜絕切屏導致頁面銷毀重建,需要加上screenSize,使用設置4,即 android:configChanges="orientation|keyboardHidden|screenSize" .

Activity的四種狀態如下:

在activity處於paused或者stoped狀態下,如果系統內存緊張,可能會被銷毀,當重回該activity時會重建,正常返回和被回收後返回的生命周期如下:

如果是回收後返回,onCreate的參數savedInstanceState不為空。

有哪些場景會觸發onNewIntent回調呢?跟啟動模式有關,首先該Activity實例已經存在,再次啟動才可能觸發。一種情況是啟動模式是singleTask或者singleInstance,無論該activity在棧中哪個位置,都會觸發onNewIntent回調,並且把上面其他acitivity移除,另一種情況是啟動模式是singleTop或者以FLAG_ACTIVITY_SINGLE_TOP啟動,並且該activity實例在棧頂,會觸發onNewIntent,如果不在棧頂是重新創建的,不會觸發。

在實際業務開發中,往往碰到需要連續退出多個activity實例,下面整理了幾種常見方法:

● 發送特定廣播
1、在需要處理連續退出的activity注冊該特定廣播;
2、發起退出的activity發送該特定廣播;
3、接收到該廣播的activity 調用finish結束頁面。
● 遞歸退出
1、用startActivityForResult啟動新的activity;
2、前一個頁面finish時,觸發onActvityResult回調,再根據requestCode和resultCode處理是否finish,達到遞歸退出的效果。
● FLAG_ACTIVITY_CLEAR_TOP
通過intent.setFlag(Intent.FLAG_ACTIVITY_CLEAR_TOP)啟動新activity,如果棧中已經有該實例,則會把該activity之上的所有activity關閉,達到singleTop啟動模式的效果。
● 自定義activity棧
1、自定義activity列表,新打開activity則加入棧中,關閉則移除棧;
2、需要退出多個activity時,則循環從棧中移除activity實例,並調用finish。

在討論Activity啟動模式經常提到任務棧,那到底什麼是任務棧?
任務是一個Activity的集合,它使用棧的方式來管理其中的Activity,這個棧又被稱為返回棧(back stack),棧中Activity的順序就是按照它們被打開的順序依次存放的。返回棧是一個典型的後進先出(last in, first out)的數據結構。下圖通過時間線的方式非常清晰地向我們展示了多個Activity在返回棧當中的狀態變化:

taskAffinity 任務相關性,可以用於指定一個Activity更加願意依附於哪一個任務,在默認情況下,同一個應用程序中的所有Activity都具有相同的affinity, 名字為應用的包名。當然了,我們可以為每個 Activity 都單獨指定 taskAffinity 屬性(不與包名相同)。taskAffinity 屬性主要和 singleTask 啟動模式和 allowTaskReparenting 屬性配對使用,在其他情況下沒有意義。
taskAffinity 有下面兩種應用場景:

分為顯示啟動和隱式啟動。
(1)顯示啟動
直接指定待調整的Activity類名。

(2)隱式啟動
Intent 能夠匹配目標組件的 IntentFilter 中所設置的過濾信息,如果不匹配將無法啟動目標 Activity。IntentFilter 的過濾信息有 action、category、data。
IntentFilter 需要注意的地方有以下:
● 一個 Activity 中可以有多個 intent-filter
● 一個 intent-filter 同時可以有多個 action、category、data
● 一個 Intent 只要能匹配任何一組 intent-filter 即可啟動對應 Activity
● 新建的 Activity 必須加上以下這句,代表能夠接收隱式調用
<category android:name="android.intent.category.DEFAULT" />

只要匹配一個action即可跳轉,注意的是action要區分大小寫。

規則:如果intent中有category,則所有的都能匹配到intent-filter中的category,intent中的category數量可用少於intent-filter中的。另外,單獨設置category是無法匹配activity的,因為category屬性是一個執行Action的附加信息。

intent不添加category會匹配默認的,即 「android:intent.category.DEFAULT」
如果上面例子,如果去掉intent.setAction("action_name"),則會拋出異常:

規則:類似action,但data有復雜的結構,只要匹配一個data並且與data中所有屬性都一致就能匹配到Activity,只要有1個屬性不匹配,都無法找到activity。
data的結構:

data 主要是由 URI 和 mimeType 組成的。
URI 可配置很多信息,的結構如下:

與url類似,例如:

mineType:指資源類型包括文本、圖片、音視頻等等,例如:text/plain、 image/jpeg、video/* 等

下面看下data匹配的例子:
只匹配scheme

只匹配scheme也是能匹配到activity的。

匹配scheme、host、port
將上面的data改為

匹配mineType

如果有mineType,則不能僅設置setData或setMineType了,因為setData會把mineType置為null,而setMineType會把data置為null,導致永遠無法匹配到activity,要使用setDataAndType。

使用scheme的默認值contentfile

注意該方法需要在startAtivity方法或者是finish方法調用之後立即執行,不能延遲,但可以在子線程執行。

而在windowAnimationStyle中存在四種動畫:
activityOpenEnterAnimation // 打開新的Activity並進入新的Activity展示的動畫
activityOpenExitAnimation // 打開新的Activity並銷毀之前的Activity展示的動畫
activityCloseEnterAnimation //關閉當前Activity進入上一個Activity展示的動畫
activityCloseExitAnimation // 關閉當前Activity時展示的動畫

overridePendingTransition的方式比較生硬,方法也比較老舊了,不適用於MD風格,google提供了新的轉場動畫ActivityOptions,並提供了兼容包ActivityOptionsCompat。

我們知道在onCreate和onResume裡面直接獲取到控制項寬高為0,那有什麼辦法獲取到控制項的實際寬高?只要有onWindowFocusChanged、view.post、ViewTreeObserver三種方式獲取。

當用戶點擊桌面圖標啟動APP時,背後的流程如下:

我們看到的手機桌面是Launch程序的界面,點擊應用圖標會觸發點擊事件,調用startActivity(intent),然後通過Binder IPC機制,與ActivityManagerService(AMS)通訊,AMS執行一系列操作,最終啟動目前應用,大概流程如下:

通過PackageManager的resolveIntent()收集跳轉intent對象的指向信息,然後通過grantUriPermissionLocked()方法來驗證用戶是否有足夠的許可權去調用該intent對象指向的Activity。如果有許可權,則在新的task中啟動目標activity,如果發現沒有進程,則先創建進程。

如果進程不存在,AMS會調用startProcessLocked創建新的進程,在該方法中,會通過socket的通訊方式通知zygote進程孵化新的進程並返回pid,在新的進程中會初始化ActivityThread,並依次調用Looper.prepareLoop()和Looper.loop()來開啟消息循環。

創建好進程後下一步要將Application和進程綁定起來,AMS會調用上一節創建的ActivityThread對象的bindAppliction方法完成綁定工作,該方法會發送一條BIND_APPLICATION的消息,最終會調用handleBindApplication方法處理消息,並調用makeApplication方法處理消息,載入APP的classes到內存中。

通過前面的步驟,系統已經擁有了該Application的進程,後續的啟動則是從已存在其他進程中啟動Acitivity,即調用realStartAcitvityLocked,該方法會調用Application的主線程對象ActivityThread的sheleLaunchActivity方法,在方法中會發送LAUNCH_ACTIVITY到消息隊列,最終通過handleLaunchActivity處理消息,完成Acitivty的啟動。

Activity
Activity 的 36 大難點,你會幾個?「建議收藏」
[譯]Android Application啟動流程分析

閱讀全文

與androidactivity棧管理相關的資料

熱點內容
泰安汽車解壓郵政網點 瀏覽:409
泰國鬼片在線觀看免費收看 瀏覽:695
彼時曾相伴免費觀看完整版 瀏覽:254
網站在線觀看什 瀏覽:159
食嬰鬼整部電影 瀏覽:360
印度電影愛經 瀏覽:642
搜播比神馬更好看的影視 瀏覽:82
特警力量同人小說 瀏覽:253
葉天明柳韻為主角的小說全文免費閱讀 瀏覽:929
比愛戀尺度大的電影 瀏覽:135
主人公叫楊凡的小說 瀏覽:860
在船上做皮肉生意的電影 瀏覽:655
倫理電影飛在天上的船 瀏覽:224
求個網址能在線看 瀏覽:549
美國古埃及電影 瀏覽:78
韓國電影成人學院演員有誰 瀏覽:957
美國大胸電影 瀏覽:140
主角重生老北京的小說 瀏覽:199
邵氏100部恐怖影片 瀏覽:101
青春期2裡面的跳舞的歌 瀏覽:37