2009年8月20日

What is the Intent

在一個Android應用中,主要是由四種組件組成的,這四種組件是 Activitty, service, boardcase receiver,content provider 。 而這四種組件是獨立的,它們之間可以互相調用,協調工作,最終組成一個真正的Android應用。在這些組件之間的通訊中,主要是由Intent協助完成 的。Intent負責對應用中一次操作的動作、動作涉及數據、附加數據進行描述,Android則根據此Intent的描述,負責找到對應的組件,將 Intent傳遞給調用的組件,並完成組件的調用。因此,Intent在這裡起著一個媒體中介的作用,專門提供組件互相調用的相關信息,實現調用者與被調 用者之間的解耦。
例如,在一個聯繫人維護的應用中,當我們在一個聯繫人列表屏幕(假設對應的Activity為listActivity)上,點擊某個聯繫人後,希望能夠 跳出此聯繫人的詳細信息屏幕(假設對應的Activity為detailActivity),為了實現這個目的,listActivity需要構造一個 Intent,這個Intent用於告訴系統,我們要做「查看」動作,此動作對應的查看對象是「某聯繫人」,然後調用startActivity (Intent intent),將構造的Intent傳入,系統會根據此Intent中的描述,到ManiFest中找到滿足此Intent要求的Activity,系 統會調用找到的Activity,即為detailActivity,最終傳入Intent,detailActivity則會根據此Intent中的描 述,執行相應的操作。

一、抽象描述要描述什麼
在Android參考文檔中,對Intent的定義是執行某操作的一個抽象描述(確實很抽象)。我們先來看看這裡的抽象描述,到底描述了什麼。
首先,是要執行的動作(action)的一個簡要描述,如VIEW_ACTION(查看)、EDIT_ACTION(修改)等,Android為我們定義了一套標準動作:
  • MAIN_ACTION
  • VIEW_ACTION
  • EDIT_ACTION
  • PICK_ACTION
  • GET_CONTENT_ACTION
  • DIAL_ACTION
  • CALL_ACTION
  • SENDTO_ACTION
  • ANSWER_ACTION
  • INSERT_ACTION
  • DELETE_ACTION
  • RUN_ACTION
  • LOGIN_ACTION
  • CLEAR_CREDENTIALS_ACTION
  • SYNC_ACTION
  • PICK_ACTIVITY_ACTION
  • WEB_SEARCH_ACTION
此外,我們還可以根據應用的需要,定義我們自己的動作,並可定義相應的Activity來處理我們的自定義動作。

其次,是執行動作要操作的數據 (data),Android中 採用指向數據的一個URI來表示,如在聯繫人應用中,一個指向某聯繫人的URI可能為:content://contacts/1。這種URI表示,通過 ContentURI這個類來描述,具體可以參考android.net.ContentURI類的文檔。
以聯繫人應用為例,以下是一些action / data對,及其它們要表達的意圖:
  • VIEW_ACTION content://contacts/1 -- 顯示標識符為"1"的聯繫人的詳細信息
  • EDIT_ACTION content://contacts/1 -- 編輯標識符為"1"的聯繫人的詳細信息
  • VIEW_ACTION content://contacts/ -- 顯示所有聯繫人的列表
  • PICK_ACTION content://contacts/ -- 顯示所有聯繫人的列表,並且允許用戶在列表中選擇一個聯繫人,然後把這個聯繫人返回給父activity。例如:電子郵件客戶端可以使用這個Intent,要求用戶在聯繫人列表中選擇一個聯繫人

另外,除了action和data這兩個重要屬性外,還有一些附加屬性:
  • category(類別),被執行動作的附加信息。例如 LAUNCHER_CATEGORY 表示Intent 的接受者應該在Launcher中作為頂級應用出現;而ALTERNATIVE_CATEGORY表示當前的Intent是一系列的可選動作中的一個,這 些動作可以在同一塊數據上執行。
  • type(數據類型),顯式指定Intent的數據類型(MIME)。一般Intent的數據類型能夠根據數據本身進行判定,但是通過設置這個屬性,可以強制採用顯式指定的類型而不再進行推導。
  • component(組件),指定Intent的的目標組件的類名稱。通常 Android會根據Intent 中包含的其它屬性的信息,比如action、data/type、category進行查找,最終找到一個與之匹配的目標組件。但是,如果 component這個屬性有指定的話,將直接使用它指定的組件,而不再執行上述查找過程。指定了這個屬性以後,Intent的其它所有屬性都是可選的。
  • extras(附加信息),是其它所有附加信息的集合。使用extras可以為組件提供擴展信息,比如,如果要執行「發送電子郵件」這個動作,可以將電子郵件的標題、正文等保存在extras裡,傳給電子郵件發送組件。

總之,action、 data/type、category和extras 一起形成了一種語言。這種語言使系統能夠理解諸如「查看某聯繫人的詳細信息」之類的短語。隨著應用不斷的加入到系統中,它們可以添加新的action、 data/type、category來擴展這種語言。應用也可以提供自己的Activity來處理已經存在的這樣的「短語」,從而改變這些「短語」的行 為。

二、Android如何解析Intent
在應用中,我們可以以兩種形式來使用Intent:
  • 直接Intent:指定了component屬性的Intent(調用setComponent(ComponentName)或者setClass(Context, Class)來指定)。通過指定具體的組件類,通知應用啟動對應的組件。
  • 間接Intent:沒有指定comonent屬性的Intent。這些Intent需要包含足夠的信息,這樣系統才能根據這些信息,在在所有的可用組件中,確定滿足此Intent的組件。
對於直接Intent,Android不需要去做解析,因為目標組件已經很明確,Android需要解析的是那些間接Intent,通過解析,將 Intent映射給可以處理此Intent的Activity、IntentReceiver或Service。
Intent解析機制主要是通過查找已註冊在AndroidManifest.xml中的所有IntentFilter及其中定義的Intent,最終找 到匹配的Intent。在這個解析過程中,Android是通過Intent的action、type、category這三個屬性來進行判斷的,判斷方 法如下:
  • 如果Intent指明定了action,則目標組件的IntentFilter的action列表中就必須包含有這個action,否則不能匹配;
  • 如果Intent沒有提供type,系統將從data中得到數據類型。和action一樣,目標組件的數據類型列表中必須包含Intent的數據類型,否則不能匹配。
  • 如果Intent中的數據不是content: 類型的URI,而且Intent也沒有明確指定它的type,將根據Intent中數據的scheme (比如 http: 或者 mailto: ) 進行匹配。同上,Intent 的scheme必須出現在目標組件的scheme列表中。
  • 如果Intent指定了一個或多個category,這些類別必須全部出現在組建的類別列表中。比如Intent中包含了兩個類別:LAUNCHER_CATEGORY 和 ALTERNATIVE_CATEGORY,解析得到的目標組件必須至少包含這兩個類別。

沒有留言: