1、onWindowFocusChanged微信
有時咱們須要測量一個Activity多長時間才能顯示出來,那麼在代碼中打點計時的時機選在哪兒呢?在onCreate和onResume執行完成後,Activity的界面仍不可見,在onResume以後,framework還會回調一個叫onWindowFocusChanged的函數,它表示用戶是否已經能夠與Activity的界面進行交互了。onWindowFocusChanged爲true意味着Activity的界面已經可以被用戶看到了(天然也能和用戶交互了)。實際上activity變爲visible的時間點出如今onWindowFocusChanged以前,可是這個狀態只能在ActivityManagerService中獲取,在客戶端仍是隻能經過onWindowFocusChanged做爲界面可見或不可見的標誌。app
在界面變爲不可見時,先調用onPause,而後再是onWindowFocusChanged爲false。這也容易理解,onPause原本就是Activity被部分遮住時調用的,調用完onPause後纔會讓界面不能與用戶繼續交互。函數
若是想加快Activity的啓動時間,把在onCreate裏一些耗時操做挪到onResume裏,有時會發現並無什麼變化,因此若是要想先讓Activity的界面儘快展示給用戶仍是得把這些邏輯放在onWindowFocusChanged變爲true以後執行。佈局
2、onUserLeaveHint動畫
這個回調函數主要用來監聽按Home鍵退出到桌面的動做,發生在onPause以前。在啓動一個新的Activity時,ActivityStackSupervisor裏會調用startActivityUncheckedLocked,在它裏面會給mUserLeaving賦值。mUserLeaving用於指示當前activity退到後臺時函數onUserLeaving是否被調用。.net
可見,只有當設置了FLAG_ACTIVITY_NO_USER_ACTION標誌時mUserLeaving纔會爲false,其餘狀況下mUserLeaving均爲true,也就是onUserLeaveHint會被調用,註釋裏也說了onUserLeaveHint會在onPause以前被調用。xml
3、taskAffinity字符串
task是一組用來處理某一任務的Activity的集合,位於一個回退棧內,當新啓動一個應用時framework就會建立一個新的task來承載相應的Activity。taskAffinity用來描述Activity的親和性,即Activity屬於哪一個task。若是在AndroidManifest.xml的application中沒顯式定義taskAffinity,那麼缺省的affinity名字就是包名。同一affinity的Activity會被放在同一task裏,task的affinity名字由根Activity的taskAffinity決定,若是根Activity沒設taskAffinity屬性,則affinity就由application的affinity決定。get
若是taskAffinity設爲空字符串,那說明該Activity和其餘的task都不存在親和性。不一樣應用的Activity也能夠設置相同的affinity,這樣當啓動後它們就會位於同一task中。 回調函數
4、launchMode
1. standard
默認的launchMode,能夠實例化屢次。
2.singleTop
使用這種launchMode的狀況是,若是要啓動的Activity已經在棧的最頂端,那麼startActivity時再也不會從新調用它的onCreate,而是調用它的onNewIntent。但若是要啓動的Activity不在棧頂,好比A –> B à C,這時C再啓動B,就會再實例化一個新的B,棧裏面變成A à Bà C à B。
若是A中點擊一個button來啓動B,但系統反應慢,用戶在極短的時間內點了兩次,若是是B是standard,則會有兩個B,若是是singleTop則只會有一個。更典型的場景是用戶使用外賣App支付了一筆訂單後,從支付頁面返回到訂單詳情頁面,若是訂單的狀態有發生變化,好比商家接單了,這時通知欄會有通知,點擊通知會跳入訂單詳情頁面。若是此時訂單詳情頁面是standard的話,那麼用戶按back鍵後發現仍是在訂單詳情頁面,體驗就不好了。若是是singleTop,只需在onNewIntent裏更新狀態信息,就能夠顯示出最新的信息,而沒必要再新建立一個相同的Activity了。
3.singleTask
以這種模式啓動的Activity,若是在task中已經存在該Activity的實例,就調用它的onNewIntent方法,進入該task中。若是沒有該Activity的實例,就建立一個新的task,把該Activity做爲新task的根Activity。因此以singleTask啓動的Activity不必定會新建立一個task。須要注意的是,即便Activity位於新的task裏,按back鍵仍然會回到啓動它的上一個Activity中,雖然它們不在同一個task裏。
若是singleTask的Activity的taskAffinity和現有task的affinity相同,那就直接在現有的task裏建立該Activity,因此以singleTask啓動的Activity未必就是位於棧底的根Activity。
4.singleInstance
以這種模式啓動的Activity本身獨佔一個task,若是已經有該Activity的實例,再次啓動時會調它的onNewIntent。但以singleInstance啓動的Activity按back的行爲卻與singleTask不一樣。好比 A啓動B,B是singleInstance,B再啓動C,則B本身單獨位於一個新的task中,A和C位於一個task中,則按back鍵時,從C不會退回到B,而是先退回到A,再按back鍵再退回到B。
注意,在代碼中也能夠設置Intent的flag來控制Activity的啓動模式,代碼中動態設置的比AndroidManifest.xml中靜態寫的Android:lauchMode優先級高。
5、Intent的flags
1.FLAG_ACTIVITY_NEW_TASK
爲Activity新建立一個task,若是startActivity的context不是Activity,而是service或Application,那必定要加上這個flag。以這個flag啓動Activity的行爲跟launchMode爲singleTask的一致。但並非每次都新建立一個task,把Activity放在裏面,而是會先找是否已經有taskAffinity相同的task,若是有就把要啓動Activity放在該task裏,若是沒有taskAffinity相同的task,纔會新建一個task。
2.FLAG_ACTIVITY_SINGLE_TOP
做用同singleTop。
3.FLAG_ACTIVITY_CLEAR_TOP
啓動Activity時,若是所在task裏已經有該Activity的實例,則會清除在它上面全部的Activity。例如,task裏的Activity啓動關係是Aà Bà Cà D,而後在D啓動B時,加上了FLAG_ACTIVITY_CLEAR_TOP標誌,在B啓動後task裏就只有A和B了,C和D被清除了。若是B的launchMode是standard,那麼當它收到Intent後,會先銷燬掉原來B的實例,而後從新onCreate構建一個新的B;若是B是singleTask類型,那麼會保留原有的B的實例,調用它的onNewIntent,傳入新的Intent。
4.FLAG_ACTIVITY_CLEAR_TASK
啓動Activity時,會清除所在task裏其餘全部的Activity。例如,task裏的Activity啓動關係是A à Bà C,在B啓動C時,加上FLAG_ACTIVITY_CLEAR_TASK,那麼在C啓動後,task裏就只剩C了,A、B被清除了。若是這個應用中只有這一個task,那麼在C中按back鍵就退回到桌面了。
5.FLAG_ACTIVITY_REORDER_TO_FRONT
以該標誌啓動的Activity若是已經在task中存在,會被移動到棧頂,其餘的Activity順序不變。若是在task中不存在,則新建一個。例如,task裏的Activity啓動關係是A ->B ->C->D,在D啓動B時,加上這個flag,則B就被移到了棧頂,task裏就變成了A ->C ->D -> B了。若是B已經調了finish,但系統還沒來得及把它從task中移出,這時以FLAG_ACTIVITY_REORDER_TO_FRONT方式啓動B,則沒法啓動B。只有當B destroy之後才能夠啓動B。
6.FLAG_ACTIVITY_NO_HISTORY
這個FLAG可讓啓動的Activity一旦退出,就finish掉,再也不存在於棧中。例如,Activity的啓動關係是A-> C->D,在B啓動C時加上FLAG_ACTIVITY_NO_HISTORY,在C啓動完D後,task裏仍然是 A-> B->C->D的棧佈局,C並沒從棧中清除。當在D中按back鍵,不會退到C而是退到B,這時dumpsysactivity會發現task中沒有C了,只有A和B,在D中按back鍵時,C就finish掉了。
7.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
以這個flag啓動的Activity將不會在最近啓動的應用列表中出現。
8.FLAG_ACTIVITY_FORWARD_RESULT
咱們用startActivityForResult和setResult在兩個Activity之間傳遞數據,若是中間還隔着另外一個Activity,好比A -> B->C,要想在A和C之間用startActivityForResult和setResult的話,就要在B啓動C時加上這個參數。也就是A正常的startActivityForResult啓動B,B以FLAG_ACTIVITY_FORWARD_RESULT方式啓動C,在C中setResult,這樣當從C退回B,再退回到A,即C和B都finish後,A的onActivityResult會收到C中setResult傳的值。
9.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
這個是從最近任務列表中啓動Activity時由系統設置的,第三方應用不會用到這個標誌,系統的SystemUI在最近任務列表中才會設這個標誌。
10.FLAG_ACTIVITY_NO_ANIMATION
要啓動Activity將不執行入場動畫。
11.FLAG_ACTIVITY_TASK_ON_HOME
以這個flag啓動的Activity所在的task將會位於Home所在的task之上,也就是說在這個Activity中按back鍵會回到home,而不是啓動它的那個Activity。例如,A -> B,B的taskAffinity與A不一樣,A啓動B時同時加上了FLAG_ACTIVITY_TASK_ON_HOME和FLAG_ACTIVITY_NEW_TASK這兩個標誌,那麼A和B位於不一樣的task中,若是僅是以newtask方式啓動B,那麼即便B和A不在一個task中,那麼在B中按back鍵仍是會退到A的,但加上了FLAG_ACTIVITY_TASK_ON_HOME後,按back鍵就退回到home了,此時A已經被移動到了後臺。