【Android開發日記】之入門篇(十一)——Android的Intent機制

繼續咱們的Android之路吧。今天我要介紹的是Android的Intent。html

對於基於組件的應用開發而言,不只須要構造和尋找符合需求的組件,更重要的是要將組件有機的鏈接起來,互聯互通交換信息,纔可以最終提供應用所指望的服務。而爲了可以更好地實現組件複用,充分地利用每個組件的能力,就須要這些組件鏈接的模式足夠靈活和統一,而且能夠進行動態地擴展。因此Android提供了利用Intent對象創建鏈接並實現組件通訊的模式。Intent對象是Android組件鏈接的核心,集中體現了整個組件鏈接模型的設計思想。android

 

1、Intent對象算法

Android的Intent機制最核心的設計思想,就是引入了組件管理服務做爲鏈接組件的管理者。該服務能夠經過組件的配置信息瞭解系統中每一個組件的類別和功能,從而幫助調用組件尋找符合其需求的實現組件,將調用者與實現者完全解耦。緩存

通常的Intent實現的流程圖:
數據結構

 

  1. Intent對象的構成
    Intent對象的這些做用,都是經過它的實現和設計體現出來的。從數據結構來看,Intent類的實現很是簡單,它並無包含複雜的邏輯功能,只是包含着若干個數據項。
    (1)Action項 在Intent中用來表示動做,能夠經過Intent的setAction和getAction來進行操做。在Android中定義了不少標準的動做,好比:Intent.ACTION_VIEW等。這些動做約定了    Android組件間的通訊規範,保證了組件系統的可擴展性。
    (2)Data項,當發起請求時,調用組件若是有明確的數據對象,一般就會用Data項來存儲表示。Data數據也是用字符串進行存儲,它的格式符合URI標準。因此能夠經過URI來描述數據來加強數據的做用範圍。
    (3)Type項, Type是MINE格式的字符串數據,用於描述組件可以處理的請求類型,或者補充說明Data數據的類型,它能夠經過通配符*來表示整個類別的信息。注意:Data項和Type項在不少時候是互斥使用的,當調用Intent.setType時,以前設定的Data信息就會被清空,反之亦然。但能夠經過intent.setDataAndType()來同時設置。
    (4)Category項 Category表示約束。每一個Intent對象可包含多個categroy項。而一個組件須要支持所有的Category纔可能處理請求。如一個組件須要啓動其餘應用,且但願進入的是這個應用的入口組件,這時就須要添加Intent.CATEGORY_LAUNCHER做爲約束。
    (5)Component項  它指的是目標組件的類型信息,能夠經過Intent.setComponent方法利用類名進行設置,也能夠經過Intent.setClass方法利用類型對象信息進行設置。
    (6)Extras項 Intent中數據傳輸的載體,負責將數據從調用組件傳遞到實現組件。
    (7)Flags項 Flags是一個整數型,由一系列的標誌位聚集而成。
    在組件開發中,應該遵循SDK或第三方擬定的相關規範。當一個組件須要支持特定的Action時,就須要同支持相關的Extras項和Data項相關內容。協議的完整性和正確性是整個Android Intent機制的根基。
  2. Intent對象的解析
    從實現組件的選擇來看,Intent對象能夠分爲兩類:精確描述的Intent和模糊描述的Intent。
    (1)精確描述的Intent,指的是全部帶有Component信息的Intent對象,調用組件能夠經過Intent.setComponent或Intent.setClass等方法進行設置。當組件管理服務收到Intent對象時,會先校驗其Component數據項,若是含有Component信息,組件管理服務只須要依照Component構造對應的實現組件。平時咱們用的Intent的跳轉都是用的精確Intent.
    (2)除此以外,全部不包含Component信息的Intent對象,都歸類於模糊描述的Intent.

2、Intent Filter對象
除了Intent對象,在Android的Intent機制中還有一個重要的角色:Intent Filter對象。Intent Filter對象,指的是android.content.IntentFilter類的對象,它是Intent對象的「姊妹對象」。與Intent對象相似,Intent Filter對象也包含Action、Type、Data、Catagory等數據項,每一個數據項的結構和含義,與Intent的數據項也一一對應。app

  1. Intent Filter的用途
    Intent Filter是各個組件用於描述其功能的,經過組件的Intent Filter信息,Android的組件管理應用就能夠了解和掌握各個組件所具有的能力和可以處理的請求。當組件管理服務接收到調用組件發送來的基於模糊描述的Intent對象時,會與全部組件的Intent Filter信息進行匹配計算,尋找符合需求的實現組件。
    每一個組件均可以有任意數量的Intent Filter。組件包含的Intent Filter對象越多,說明他能接受Intent請求範圍越廣,同時,其實現也會越複雜。
  2. Intent Filter的範例
             <activity  android:name="com.example.activitydemo.SecondActivity">
                 <intent-filter android:icon=""
                     android:label=""
                     android:priority="">
                     <action android:name=""></action>
                     <category android:name=""></category>
                     <data android:host=""
                         android:mimeType=""
                         android:path=""
                         android:pathPattern=""
                         android:port=""
                         android:scheme=""/>
                     <!-- 能夠繼續添加相關的actio、category和data項 -->
                 </intent-filter><!-- 能夠繼續添加相關的intent-filter項 -->
                 
             </activity>

 3、Intent 匹配算法ide

當組件管理服務接受到請求組件的Intent對象後,會先查看Intent對象是否包含了目標實現組件的Component信息。若是不包括,則會從應用管理服務中獲取全部組件的Intent Filter信息,並與Intent對象相比較,選擇符合需求的實現組件。其中涉及到的就是Intent的匹配算法了。
函數

算法輸入的是進行比較的Intent對象和Intent Filter對象;若是返回值爲正,則表示匹配成功,而且,正值越大意味着匹配程度越高,流程圖以下。post


其中,Data與Type信息是Intent Filter中最複雜的數據項,其比較算法是決定Intent與Intent Filter對象匹配程度的關鍵。優化

若是Intent的對象包含Type信息,就必需要求Intent Filter的Type信息與之對應,不然,匹配也將以失敗了結;而後,若是Intent對象中含有Data項,則會將該Data項的URI信息拆分爲Scheme和Authority等部分,逐一與Intent Filter對象中對應的部分進行比較,只要二者有任何不符的地方,匹配都會失敗。

以Android原生的郵件應用爲例,它配置了以下的Intent Filter信息:

 

          <activity  android:name=".SecondActivity.MessageCompose">
             <intent-filter >
                 <action android:name="android.intent.action.VIEW" />
                 <action android:name="android.intent.action.SENDTO" />
                 <data android:scheme="mailto"/>
                 <category android:name="android.intent.category.DEFAULT"/>
                 <category android:name="android.intent.category.BROWSABLE"/>
                 <!-- 能夠繼續添加相關的actio、category和data項 -->
             </intent-filter>
             <!-- 能夠繼續添加相關的intent-filter項 -->
             
         </activity>

 

當調用者發出以下請求時,就會觸發一次意圖匹配:

                Intent intent = new Intent(Intent.ACTION_SENDTO);
                intent.putExtra(Intent.EXTRA_TEXT, "");
                //其中,mailto這部分是URI的scheme部分
                intent.setData(Uri.parse("mailto:xxx@oo.com"));
                startActivity(intent);

開始匹配檢查。ACTION包含OK—>data包含OK—>Category檢查(經過Context.startActivity函數發出請求,組件管理服務會自動爲其添加上Intent.CATEGORY_DEFAULT)OK—>匹配成功

 

4、匹配組件的選擇

若是有多個Intent Filter對象與調用組件發出的Intent對象都相匹配,就須要在全部符合條件的Intent Filter對象中進行篩選,選出最符合調用組件和用戶需求的實現組件,這就是匹配組件的選擇。而咱們能夠設定Intent Filter對象的優先級來進行設定,即經過<intent-filter>配置項中的android:priority屬性進行變動,或者經過IntentFilter.setPriority函數進行動態地修改。範圍是-1000至1000,默認爲0。

在Android的Intent機制中,經過引入第三方組件管理服務,下降了調用組件與實現組件之間的耦合,提升了整個系統的靈活性及組件的複用性,使得應用開發變得更爲簡單快捷。但同時,正是因爲第三方服務地介入增長了組件間鏈接的成本,可能會使組件間的調用不夠流暢。所以,在組件管理服務中,系統對組件的匹配和選擇過程進行了大量的優化,以提升組件調用的效率,其中包括:

(1)索引
       組件管理服務經過哈希表,爲全部Intent Filter對象的Action、Type等數據項創建索引。每一個索引項對應着一組Action相同,Type相同或者其餘數據項相同的Intent Filter對象。Intent先與索引項比較,快速地選擇出可能與Intent相匹配的Intent Filter對象。這樣,就加快了匹配速度。

(2)緩存
       所謂緩存,是將Intent與Intent Filter的匹配結果記錄下來,當再碰到相同Intent的調用時,可直接返回上次記錄的結果,從而跳過匹配的過程,加速組件的調用。

5、Intent使用的一個小例子

  1. 一個ActivityDemo工程,用以啓動其餘應用的Activity。其中的代碼爲

    public class ChangeActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button button = (Button) findViewById(R.id.button);
            Button button2 = (Button) findViewById(R.id.button2);
            button.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
    
                    Intent intent = new Intent();
                    //由於是精確啓動,這些不加都是沒問題的
                    //intent.addCategory(Intent.CATEGORY_LAUNCHER);
                    // intent.setAction(Intent.ACTION_MAIN);
                    ComponentName cn = new ComponentName(
                            "com.example.demo",//另外一個應用的包名
                            "com.example.demo.MainActivity");//要啓動的另外一個應用的類名
                    //intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    intent.setComponent(cn);
                    Log.d("TEST", intent.toString());
                    startActivity(intent);
    
                    //精確啓動的另外一種方法
                    /*Intent LaunchIntent = getPackageManager()
                            .getLaunchIntentForPackage("com.example.demo");
                    Log.d("TEST", LaunchIntent.toString());
                    startActivity(LaunchIntent);*/
                }
            });
    
            button2.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
    
                    //只能得到系統級的應用組件
                    //action爲MAIN,應用入口界面
                    Intent intent = new Intent(Intent.ACTION_MAIN);
                    intent.addCategory(Intent.CATEGORY_LAUNCHER);
                    startActivity(intent);
                    
                    //獲取全部符合的組件,包括第三方安裝的應用
                    //List<ResolveInfo> activities = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
                    //自定義對話框
                    //ShowSelectActivityDialog(activities);
                }
            });
    
        }
    
    }

     

  2. 另外一個應用,即包名爲com.example.demo的應用,其中配置文件部分爲:

    <activity
                android:name="com.example.demo.MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
  3. 安裝以上兩個應用,運行效果圖:

    點擊精確Intent,成功跳轉到另外一個應用中。
    點擊模糊Intent,出現組件選擇列表,以下圖:

PS:其中關於PackageManager的詳細用法,能夠參考這篇文章Android隨筆—PackageManager詳解

6、結束語

看到這裏,你們是否是對Intent的傳遞原理有所瞭解了呢。形象一點地說,Intent比如是插頭,而Intent Filter就比如是插座,插座的孔只要知足插頭的孔腳數量就能工做了,多了沒事,但少了就不行。

Intent是Android應用模型的核心,解決了組件間的鏈接問題。經過組件管理服務提供的Intent匹配策略,下降了組件間的耦合度,提升了平臺的靈活性,加強了組件的複用性,從根本上減輕了應用開發的負擔。

 

參考文章:(1) android Intent機制詳解 http://www.oschina.net/question/565065_67909

               (2)android intent和intent action大全  http://www.apkbus.com/android-72361-1-1.html

 

========================================

 

做者:cpacm

地址:http://www.cpacm.net/2015/03/26/Android開發日記(八)——Android的Intent機制/

相關文章
相關標籤/搜索