1.Activity的生命週期與啓動模式

1. 生命週期簡介


1.1 onCreate

表示Activity正在創建,在其中可以執行一些初始化任務。setContextView方法在其中。

1.2 onRestart

表示Activity重新啓動,典型特徵:不可見->可見

1.3 onStart

表示Activity正在啓動,典型特徵:可見,不可交互

1.4 onResume

表示Activity已經可見,典型特徵:可見,可交互

1.5 onPause

表示Activity正在停止,典型特徵:可見,不可交互,例如:Act上面出現了一個透明的Act2,此時Act1處於onPause狀態

1.6 onStop

表示Activity即將停止,典型特徵:不可見,不可交互,可做一些輕微重量級的回收任務,不可進行耗時操作。

1.7 onDestory

表示Activity即將被銷燬,典型特徵:銷燬,回收工作,資源釋放

2.Act生命週期的切換過程流程圖

其他說明:

1. 新Act採用了透明主題,舊Act不會調用onStop方法

2. 生命週期存在3組配對關係和單獨的一個onRestart

3. onStart與onResume區別:是否可交互。同理,onPause與onStop之間

4. Act1啓動Act2,先調用Act1中的onPause,後調用Act2中OnResume

書中P4~P6源碼部分沒有理解,有待回顧。

3異常情況下生命週期分析

3.1資源配置引起的Act被殺死並重新創建

簡單說,當系統配置發生了變化(橫豎屏切換),就會引起Act被殺死並重新創建。

onSaveInstanceState方法與onRestoreInstance-State方法用戶在異常情況下存儲用戶的臨時數據,和在重新啓動時恢復用戶的臨時數據。前者的調用時機在onStop之前,後者在onStart方法後被調用,中間通過一個Bundle對象作爲參數進行傳遞。

可以通過①onCreate方法和②onRestoreInstance-State來獲取onSaveInstanceState方法中所保存的用戶臨時數據,二者的區別爲:①中使用Bundle需要進行判斷null處理,而②不需要判斷,可直接使用。原因爲②被調用時,一定是有數據可以恢復的。

可恢復的數據包括文本框的用戶輸入數據,Listview的滾動位置等。當保存用戶的臨時數據時爲上級通知下級,下級進行保存(中間存在多級),View是可以保存數據的。

注意只有在異常情況下纔回去調用 onSaveInstanceState方法,onRestoreInstanceState方法

3.2內存不足時,低優先級的應用會被殺死

Act優先級(由高到低)

①前臺Act,正在與用戶進行交互的Act

②可見非前臺Act,例如:Act中彈出了一個對話框

③後臺Act,已經被暫停的Act

一個進程沒有四大組件在執行,那麼該進程會快就會被系統殺死

防止屏幕旋轉導致的Activity被系統殺死,需要在AndroidMenifest.xml中配置android:config-Changes=“orientation|screenSize”(其中screen-Size是在api13後需要添加的),此時當屏幕方向旋轉了,不會再調用onSave-InstanceState方法與onRestoreInstanceState方法,僅僅調用onConfi-guration,在其中我們可以做一些自己的處理

2. Activity的啓動模式


2.1 standard:標準模式 ,特點每次啓動Act時都會創建一個實例,新啓動的Act一般與原來的啓動者的同屬於一個任務棧

2.2 singleTop:棧頂複用模式,特點:棧頂唯一,如果新啓動的Act恰好處於棧頂,那麼不會創建新的實例,會調用onNewIntent方法

2.3 singleTask:棧內複用模式,特點:棧內存在實例則不創建新的實例,將本身移動到棧頂,原來在其之上的Act將進行出棧處理,即具有clearTop的作用。複用時也會調用onNewIntent方法。

singleTask流程圖

singleTask流程圖

2.4 singleInstance:單實例模式,具有singleTask的所有特性,具有此模式的Act只能單獨的存在在一個任務棧中。當啓動一個單實例模式Act,爲其創建一個任務棧,後續的啓動Act都會使用該實例,直到該實例被銷燬,與此同時相應的任務棧也會被銷燬。

2.5 TaskAffinify任務相關性,主要用於singleTask,allowTaskReparenting屬性配對使用

默認情況下所有的Activity所需的任務棧的名字爲應用的包名。我們可以爲每個Activity單獨指定TaskAffinify

任務棧分爲:前臺任務棧(當前與用戶交互的)和後臺任務棧

allowTaskReparenting屬性爲true時標明該Act可跨Task例:AppA—>appB(Page c)—>back->點擊桌面B,顯示的是pageC,而不是B的主界面

當代碼中設定了addFlag屬性時,其優先級高於AndroidMenifest.xml中配置launchMode

當學習act任務棧時,應該使用adb shelle dumpsys activitys來查看當前的Act

3. Activity的Flag


①FLAG_ACTIVITY_NEW_TASK:相當於”singleTask”

①FLAG_ACTIVITY_SINGLE_TOP:相當於”singleTop”

①FLAG_ACTIVITY_ClEAR_TOP:當具有Flag啓動的Act啓動時,會將棧中其上的Act進行出棧,一般與NEW_TASK一起使用。singleTask默認具有該屬性

①FLAG_ACTIVITY_EXClUDE_FROM_RECENTS:不會出現在歷史Act列表中,相當於AndroidMenifest.xml中配置android:excludeFromRecents-=”true”

4. IntentFilter的匹配規則


Intent不應該既是隱式調用又是顯式調用,如果二則並存的話以顯式調用爲主。

  • 隱式調用需要匹配IntentFilter(category,action,data)
  • 說明: 一個Activity可以擁有多個IntentFilter,多個IntentFilter之間是”或”關係,只要滿足其中的一個IntentFilter就可以啓動當前的Activity;而actiong,category,data類別間是與關係,必須全滿足纔可以。
  • 具體匹配規則如下:
1. action:
  Intent中的字符串與IntentFilter中完全一致才視爲匹配成功,多個action-,僅滿足一個匹配成功即可。如果沒有指定,action,那麼匹配失敗。action要求必須存在且必須=和過濾規則中的其中一個相同,區分大小寫。
2.category的匹配規則:
  要求Intent中滿足IntentFilter中的所有的category纔算匹配成功。startActivity和startActivityForResult中默認對intent添加了android.intnte.category.DEFAULT這個屬性。所以爲了是Activity能夠接受隱式調用,就必須在intent-fil,ter中指定android-intent-category.DEFAULT這個屬性。
3.data的匹配規則:
  與action類似,如果過濾規則中定義了data,那麼Intent中必須也要有定義可匹配的data。
  data的結構:mimeType(媒體結構)和URI
#####  URI結構:\://\:\/[\|\|\]
例如:content:..com.example.project:200/folder/subfloder/etc
   http://www.baidu.com:80/search/info
  Scheme:URI的模式:http、file、content等,如果URI中沒有Scheme,那麼整個URI其他參數都是無效的,即該URI是無效的。HOST:主機名,必須有。Port:端口號,只有指定了Scheme,HOST時,Port纔有效。path,pathPattern,pathPrefix表示路徑信息。URI的默認值爲:content/file。注意:使用intent傳遞date,type時,不能僅僅調用setType,setData,因爲他們各自調用會清空對方,所以要使用setdataAndType方法。data支持合併,拆分的寫法。
IntentFilter的匹配規則對Service和BroadcastReceiver也是使適用的。不過系統建議調用Service時,使用顯示的調用方式。
  在使用intent隱式調用activity時,應該先調用PackageManager的resolveActivity方法或者Intent的resolveActivity的方法,如果找不到就會返回null。調用方法時,第二個參數傳遞爲:MATCH_DEAFAULT_ONLY,這個標記表明僅僅查找聲明瞭android.intent.category.DEAFAULT的ACtivity。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章