Intent和IntentFilter詳解

Intent用於啟動Activity,Service, 以及BroadcastReceiver三種組件, 同時還是組件之間通信的重要媒介。

使用Intent啟動組件的優勢
1, Intent為組件的啟動提供瞭一致的編程模型。無論想要啟動的組件是Activity,Service, 還是BroadcastReceiver,都可以使用Intent封裝啟動的意圖。
2, 在某些時候, 應用程序隻是想啟動具有某種特征的組件, 並不想和某個特定的組件耦合。使用Intent可以方便的達到這種高層次解耦的目的。

Intent的Component屬性
Intent對象的setComponent(ComponentNamecomp)方法用於設置Intent的Component屬性。ComponentName包含如下幾個構造器:
ComponentName(Stringpkg, String cls)
ComponentName(Contextpkg, String cls)
ComponentName(Contextpkg, Class<?> cls)
由以上的構造器可知, 創建一個ComponentName對象需要指定包名和類名–這就可以唯一確定一個組件類, 這樣應用程序即可根據給定的組件類去啟動特定的組件。例如:
ComponentName comp =new ComponentName(FirstActivity。this,SecondActivity。class);
Intent intent = newIntent();
intent。setComponent(comp);
以上三句代碼創建瞭一個intent對象, 並為其指定瞭Component屬性, 完全等價於下面的代碼:
Intent intent = newIntent(FirstActivity。this,SecondActivity。class);
除瞭使用setComponent()之外, 還可以使用setClass(),setClassName()來顯式指定目標組件, 還可以調用getComponent()方法獲得Intent中封裝的ComponentName對象。
當程序采用這種形式啟動組件時, 在Intent中明確的指定瞭待啟動的組件類, 此時的Intent屬於顯式intent, 顯式Intent應用場合比較狹窄, 多用於啟動本應用中的component,因為這種方式需要提前獲知目標組件類的全限定名。而隱式Intent則通過Intent中的action,category, data屬性指定目標組件需要滿足的若幹條件, 系統篩選出滿足所有條件的component,從中選擇最合適的component或者由用戶選擇一個component作為目標組件啟動。
如果Intent中指定瞭ComponentName屬性, 則Intent的其他屬性將被忽略。

Intent的Action屬性
action屬性是一個字符串, 代表某一種特定的動作。 Intent類預定義瞭一些action常量, 開發者也可以自定義action。一般來說, 自定義的action應該以application的包名作為前綴, 然後附加特定的大寫字符串, 例如"cn。xing。upload。action。UPLOAD_COMPLETE"就是一個命名良好的action。
Intent類的setAction()方法用於設定action,getAction()方法可以獲取Intent中封裝的action。
以下是Intent類中預定義的部分action:
ACTION_CALL–目標組件為activity,代表撥號動作;
ACTION_EDIT–目標組件為activity,代表向用戶顯示數據以供其編輯的動作;
ACTION_MAIN–目標組件為activity,表示作為task中的初始activity啟動;
ACTION_BATTERY_LOW–目標組件為broadcastReceiver,提醒手機電量過低;
ACTION_SCREEN_ON–目標組件為broadcast,表示開啟屏幕。

Intent的Category屬性
category屬性也是一個字符串, 用於指定一些目標組件需要滿足的額外條件。 Intent對象中可以包含任意多個category屬性。 Intent類也預定義瞭一些category常量, 開發者也可以自定義category屬性。
Intent類的addCategory()方法為Intent添加Category屬性,getCategories()方法用於獲取Intent中封裝的所有category。
以下是Intent類中預定義的部分category:
CATEGORY_HOME–表示目標activity必須是一個顯示homescreen的activity;
CATEGORY_LAUNCHER–表示目標activity可以作為task棧中的初始activity,常與ACTION_MAIN配合使用;
CATEGORY_GADGET–表示目標activity可以被作為另一個activity的一部分嵌入。

Intent的Data屬性
data屬性指定所操作數據的URI。 data經常與action配合使用, 如果action為ACTION_EDIT,data的值應該指明被編輯文檔的URI; 如果
action為ACTION_CALL,data的值應該是一個以"tel:"開頭並在其後附加號碼的URI; 如果action為ACTION_VIEW,data的值應該是一個以"http:"開頭並在其後附加網址的URI。。。
Intent類的setData()方法用於設置data屬性,setType()方法用於設置data的MIME類型,setDataAndType()方法可以同時設定兩者。可以通過getData()方法獲取data屬性的值, 通過getType()方法獲取data的MIME類型。

Intent的Extra屬性
通過Intent啟動一個component時, 經常需要攜帶一些額外的數據過去。攜帶數據需要調用Intent的putExtra()方法, 該方法存在多個重載方法, 可用於攜帶基本數據類型及其數組, String類型及其數組,  Serializable類型及其數組,Parcelable類型及其數組, Bundle類型等。Serializable和Parcelable類型代表一個可序列化的對象, Bundle與Map類似,可用於存儲鍵值對。

Intent的Flag屬性
flag屬性是一個int值, 用於通知android系統如何啟動目標activity,或者啟動目標activity之後應該采取怎樣的後續操作。所有的flag都在Intent類中定義, 部分常用flag如下:
FLAG_ACTIVITY_NEW_TASK–通知系統將目標activity作為一個新task的初始activity;
FLAG_ACTIVITY_NO_HISTORY–通知系統不要將目標activity放入歷史棧中;
FLAG_FROM_BACKGROUND–通知系統這個Intent來源於後臺操作, 而非用戶的直接選擇。。。

IntentFilter類
IntentFilter類表示Intent過濾器, 大部分情況下, 每一個component都會定義一個或多個IntentFilter,用於表明其可處理的Intent。
一般來說,component的IntentFilter應該在AndroidManifest。xml文件中定義。
定義的方法: 在<activity>,<receiver>, <service>元素中增加一個或多個<intent-filter>子元素。如:
<!– 聲明作為程序入口的Activity–>
<activityandroid:name="。FirstActivity">
       <intent-filter>
               <action android:name="android。intent。action。MAIN"/>
               <category android:name="android。intent。category。LAUNCHER"/>
       </intent-filter>
</activity>

IntentFilter與隱式Intent
android系統處理隱式Intent時, 會比較Intent和IntentFilter的action,data, category屬性, 如果以上3個屬性全都相符的話, 則IntentFilter所屬的component就可以作為目標組件的候選(存在多個符合條件的component時)。
1。測試action屬性。 intent最多隻能定義1個action, 而filter可以定義1個或多個action。
通過action測試的條件為: filter定義瞭intent的action。例如intent的action為"android。intent。action。MAIN",則定義瞭"android。intent。action。MAIN"這個action的filter都能通過action測試(當然, filter還可以包含更多額外的action)。
如果filter沒有定義action, 則這個filter將阻塞所有intent。如果intent沒有定義action, 那麼隻要filter定義瞭action就可以通過action測試。
2。測試category屬性。 intent可以任意多個category,filter也可以任意個category。通過category測試的條件為: filter定義瞭intent的所有category。例如intent定義瞭"android。intent。category。DEFAULT"和"cn。xing。intent。category。UPLOAD"這2個category,則定義瞭以上2個category屬性的filter才能通過測試(當然, filter還可以包含更多額外的category)。
根據上面的規則, 如果一個intent沒有定義category,則所有filter都可以通過category測試。但是有一種例外: 以startActivity(intent)方式啟動一個activity時, 系統為會intent增加一個值為"android。intent。category。DEFAULT"的category,這就意味著每一個期望通過category測試的activity,都要在其filter中定義"android。intent。category。DEFAULT"(除瞭作為程序入口的activity)。
3。測試data屬性。 intent最多隻能定義1個data,filter則可以定義多個data。
通過data測試的條件為:
a。如果intent沒有指定data和data type,則隻有沒有定義data和datetype的filter才能通過測試;
b。如果intent定義瞭data沒有定義datatype, 則隻有定義瞭相同data且沒有定義datetype的filter才能通過測試;
c。如果intent沒有定義data卻定義瞭datatype, 則隻有未定義data且定義瞭相同的datatype的filter才能通過測試;
d。如果intent既定義瞭data也定義瞭datatype, 則隻有定義瞭相同的data和datatype的filter才能通過測試。
data屬性是一個URI, URI中包含scheme,host, post和path, 典型的URI為:
scheme://host:port/path
scheme, host, post和path都是可選的。比較2個data時, 隻比較filter中包含的部分。比如filter的一個data隻是指定瞭scheme部分, 則測試時隻是比較data的scheme部分, 隻要兩者的scheme部分相同, 就視為"相同的data"。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。