繼續咱們的Android之路吧。今天我要介紹的是Android的Intent。html
對於基於組件的應用開發而言,不只須要構造和尋找符合需求的組件,更重要的是要將組件有機的鏈接起來,互聯互通交換信息,纔可以最終提供應用所指望的服務。而爲了可以更好地實現組件複用,充分地利用每個組件的能力,就須要這些組件鏈接的模式足夠靈活和統一,而且能夠進行動態地擴展。因此Android提供了利用Intent對象創建鏈接並實現組件通訊的模式。Intent對象是Android組件鏈接的核心,集中體現了整個組件鏈接模型的設計思想。android
1、Intent對象算法
Android的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
<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使用的一個小例子
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); } }); } }
<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>
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機制/