Intent的那些些事兒,Intent些事兒
請原諒我用這麼文藝的標題來闡釋一顆無時無刻奔騰著的2B青年的心。可是今天要介紹的Intent絕不2B,甚至在我看來,或許還有些許飄逸的味道,至於飄逸在哪裡呢?那我們就好好來剖析剖析Intent和它的好搭檔IntentFilter的基友情。
開場告白
Intent在Android大家庭中是一個活潑的小男孩,從小就是交際草。在代碼中,Activity、Service、BroadcastReceiver這三個重要的大媽級重量組件,之間的調用關聯都是依靠Intent去交流的,例如Activity的startActivity(),Service的startService()、bindService(),BroadcastReceiver的sendBroadcast()、sendOrderBroadcast()等,其中都是需要攜帶一個Intent(或IntentFilter)的參數。
當然Intent中要指定要啟動組件的資訊,或明顯活隱晦。明顯的就是顯式啟動:舉個例子來說就是Intent你去把這東西交給某某(名字)Activity大媽。隱晦的是隱式啟動:當然得不免俗得給例子就是Intent你把這個東東交給昨晚和我一起在菜市場跳廣場舞的那個胖大媽,其中廣場舞和胖就把某大媽給赤果果的定位了。這就是Intent的兩種匹配方式,我都覺得我自己說的怪抽象的了。
接下來就是介紹IntentFilter的好時機了,它就是大媽的兒子(組件的攔截器)。當如果Intent隱式啟動時,Intent會找他的一群小夥伴IntentFilter來,然後問他們說,你們誰的媽昨晚去菜市場跳廣場舞了?你們誰的媽又好胖好胖的?然後IntentFilter各想各媽,哎呀,其中一個IntentFilter拍拍腦袋說,這不就是我媽嗎!然後他就屁顛屁顛的領著Intent去找某Activity媽把東東交給她了。
為了避免大家看不懂上面的例子,我還是發揚一下2B青年的社會責任感,用比較教條的語言來介紹一下Intent和IntentFilter:Intent是一個意圖對象,組件可以通過設定Intent來啟動另外一個組件,有顯式啟動和隱式啟動兩種方法,顯式啟動直接指定要啟動的組件的名字,隱式啟動則指定action、category、data等來啟動合格組件;其中的IntnetFilter就是一個意圖過濾器,它會設定一些過濾規則如action、category、data等,如果Intent中的action、category、data與過濾器中相匹配,則為啟動該過濾器的組件。
碼點代碼
攻城獅的思維就是不見代碼不給贊,所以我還是得老老實實得碼幾個代碼出來撐撐場子。但是Intent的顯式啟動和隱式啟動代碼度娘一下幾大頁,在這裡再貼上來就對不起人民群眾了。所以呢,我就記錄點關鍵代碼,如果後面犯失憶了也可以回來偵查一下容易忘的知識。
顯式啟動Activity、Service:
Intent intent1 = new Intent(getApplicationContext(), MyActivity.class);startActivity(intent1);//啟動Activity組件startActivityForResult(intent1, 1);//啟動有返回的Activity
Intent intent2 = new Intent(getApplicationContext(), MyService.class);startService(intent2);//啟動ServicebindService(intent2, conn, 1);//綁定Service
隱式啟動Activity、Service:
Intent intent1 = new Intent();intent1.setAction("com.net168.test.action.myactivity");startActivity(intent1);//啟動Activity組件Intent intent2 = new Intent(); intent1.setAction("com.net168.test.action.myservice");startService(intent2);//啟動ServicebindService(intent2, conn, 1);//綁定Service
發送廣播:
Intent intent = new Intent();intent.setAction("com.net168.test.action.mybroadcast");sendBroadcast(intent);//發送普通廣播sendOrderedBroadcast(intent, null);//發送有序廣播
其實很簡單,簡單得我這的不好意思介紹了。。。
Intent的家世於IntentFilter的糾結
Intent的背景很複雜,複雜到比一些不入流的HEI社會還複雜些。大體來說,Intent大致包含了Component、Action、Categroy、Data、Type、Extra和Flag這七大金剛(屬性),後面我們就好好解釋這些大哥大姐們。
Component:它需要接受一個ComponentName的對象,建立一個ComponentName需要指定包名和類名--這就唯一確定了一個組件類,這樣程式就可以通過給定的組件類去啟動相應的組件;所以我們可以從這裡重新給顯式啟動和隱式啟動分個類,一般如果明確指定ComponentName時就是顯式啟動,反之就是隱式啟動。另外我們可以直接在執行個體化Intent時在建構函式中傳入上下文和類名也可以直接幫我們設定了ComponentName,如Intent(this,MyActivity.class),推薦這種方式,比較簡潔。
Action:Action要完成一個抽象的動作,但具體由哪個組件來完成則不確定,需要根據IntentFilter來確定組件;在Intent中,Action最多隻能有1個,而在IntentFilter中Action可以有多個。這是隱式啟動一個組件最基礎的屬性。
Category:它為Action增加額外的類別資訊,因為Action可以啟動到多個組件,但是如果往下更詳細的分析要啟動的組件,可以通過Category來進行攔截;在IntentFilter和Intent中Category可以有多個。任何一個IntentFilter的預設存在一個Intent.CATEGORY_DEFAULT的屬性。
Data、Type:這兩個算是比較親的屬性。
Data屬性通常用於向Action提供操作的資料,其值為一個Uri對象,Uri對象滿足 scheme://host:port/path 的格式,如 content://com.android.contacts/contacts/1,其中content是scheme的部分、com.android.contacts是host的部分、port部分被省略、contacts/1是path的部分。
Type屬性用於指定該Data所指定Uri對應的MIME類型,可以是所以自訂的類型,只要符合abc/xyz格子的字串即可。
在使用中,我們要知道這兩個屬性會相互覆蓋:如果Intent先設定Data屬性,後設定的Type屬性將會把Data屬性覆蓋掉,反之同理。所以如果要設定Data和Type屬性的話需要調用Intent的setDataAndType()的方法。
Extra:Extra是用於多量的資料交換,它的對象是一個Bundle對象。
Flag:Flag屬性是為了該Intent添加一些額外的控制旗標,可以通過addFlag()添加控制旗標,通常可以通過它來控制Activity的啟動效果和啟動方式。
這七個屬性中,Intent與IntnetFilter匹配的匹配規則在在於Action、Category、data、Type這幾個屬性中,具體規則如下:
Action的匹配規則:
1、如果Intent中包含action_A,而在IntentFilter中只要存在action_A這個字串,無論是否還有其他的action_B、action_C,這個Intent都能被IntnetFilter成功匹配。
2、如果如果Intent中包含action_A,只要IntnetFilter中不存在action_A的話,IntentFilter就不能匹配到Intnet。
3、如果Intent中不存在任何action_x,只要IntnetFilter中存在任意一個action_x的話,Filter就能匹配上Intent。
4、如果IntentFilter不存在任何action_x,則無論Intent中無論存在任何action_x或者沒有任何action_x的話,兩者是完全不能匹配上的。
Category的匹配規則:
這個匹配關係較為簡單,只要Intent中所有category在IntentFilter中都存在,則Intent可以匹配上IntnetFilter,不論此時Intentfilter中還存在其它的category。舉個例子,如果Intent中存在category_A、category_B,而Intentfilter中存在category_A、category_B、category_C,則可以匹配;如果而Intentfilter中存在category_A、category_D、category_C,因為Intentf中不存在Intent中存在的category_B,所以匹配失敗。
Data和Type的匹配規則:
data由URI來描述和定位,URI由三部分組成,scheme://host:port/path 模式://主機:連接埠/路徑
此外在事件中,還可以設定data的MIME類型,作為事件的datatype屬性。
首先明確一個匹配原則,就是對於URI的匹配,只比較IntentFilter中聲明的部分。
部分匹配原則:只要IntentFilter中聲明的部分匹配成功,就認為整個URI匹配成功。
舉例來說, content://com.silenceburn.SdCardTester:1000/mydata/private/
和IntentFilter定義為 content://com.silenceburn.SdCardTester:1000/ 是可以匹配的。
注意IntentFilter中並沒有定義path部分,但是依然可以匹配成功,因為IntentFilter不聲明的部分不進行比較。
換句話講,任何符合content://com.silenceburn.SdCardTester:1000/的事件,無論path是什麼,都可以匹配成功。
接下來是真正的data部分的,也就是URI的匹配規則如下:
1. 如果data的URI和datatype為空白,則 filter 的URI和type也必須為空白,才能匹配成功
2. 如果data的URI不為空白,但是datatype為空白,則 filter 必須定義URI並匹配成功,且type為空白,才能匹配成功
3. 如果data的URI為空白,但是datatype不為空白,則 filter 必須URI為空白,定義type並匹配成功,才能匹配成功
4. 如果data的URI和data都不為空白,則 filter 的URI和type都必須定義並匹配成功,才能匹配成功。對於URI部分,有一個特殊處理,就是即使IntentFilter沒有定義URI,content和file兩種URI也作為既存的URI存在。
除了明朝那些事兒,還有什朝什事兒?
流血的仕途
如果這是宋史
那是漢朝
原來這才是春秋
這幾本都不錯 ,你可以看看
那年那兔那些事兒吧裡氣氛是什情況?裡面都是些什樣的人說?算是愛國吧?
如果你在網上說:我愛黨愛國!那麼人們會罵你五毛
如果你在網上說:我不愛黨也不愛國!那麼人們會罵你JY美分
如果你在網上說:我愛黨但不愛國!人們會說你深井冰
如果你在網上說:我愛國但不愛黨!五毛會說你偽君子,JY美分們會說你不明智心存幻想,但是大多數人們會說你很正常!
所以網上會有很多人說:我愛國但不愛黨!