流程簡介
啟動一個Activity可能是我們在Android編程中最長用的功能之一了,方式也很簡單,就是調用Context類的startActivity方法。可能有些開發者誤認為startActivity就是通過直接調用另一個Activity子類的初始化方法來喚起另一個Activity的,其實不然。
當你在使用startActivity時,這個調用會被發送給屬于系統一部分的ActivityManager一個信息。由ActivityManager來創建該Activity實例并且調用它的onCreate方法。流程如下圖:
這里寫圖片描述
有人可能會問,那系統如何知道啟動哪一個Activity的呢?答案是通過Intent這個組件,以下是摘自Android源碼的兩個最基本的Intent構造函數:
public Intent(Context packageContext, Classlt;?gt; cls) { mComponent = new ComponentName(packageContext, cls); } public Intent(String action) { setAction(action); }
第一個構造函數中,ActivityManager可以獲得包名,和具體的類名,進而啟動這個Activity。第二個構造函數中,ActivityManager還可以通過一個叫action的字符串來找到對應的Activity來啟動。我們可以感受出來,通過此種架構,可以讓Activity的啟動具有更大的靈活性,也更加松耦合。既然ActivityManager是系統一部分,那在每個應用安裝時,也就需要告訴系統自己哪些部分是可以被這種方式啟動的,此時我們就有了AndroidManifest文件,所以才有了我們需要在AndroidManifest文件中聲明Activity這個組件的做法,否則就會報ActivityNotFoundException這個異常。
顯示和隱式啟動
理解了上面的流程,我們再來看下啟動的兩種方式就很簡單了,一個叫顯示啟動,一個叫隱式啟動。我們來舉兩個顯示啟動的例子
Intent intent = new Intent(this, SecondActivity.class); startActivity(intent);
或者
ComponentName componentName = new ComponentName(this, SecondActivity.class); // 或者 new ComponentName(this, quot;com.example.SecondActivityquot;); // 或者 new ComponentName(this.getPackageName(), quot;com.example.SecondActivityquot;); Intent intent = new Intent(); intent.setComponent(componentName); startActivity(intent);
第一種我想大家再熟悉不過了,第二種在了解啟動流程后耶比較容易理解,如果把第一個參數的包名換成其他App的,還可以直接啟動其它App。
我們再來介紹下隱式啟動,在介紹之前,我們需要了解一個標簽 lt;intent-filtergt;
,從字面上來看,很好理解,就是用來過濾掉一些intent。讓只有具備處理特定intent的Activity才會被啟動。比如在AndroidManifest中有如下聲明:
lt;activity android:name=quot;com.example.SecondActivityquot;gt; lt;intent-filtergt; lt;action android:name=quot;12345quot;/gt; lt;category android:name=quot;android.intent.category.DEFAULTquot;/gt; lt;/intent-filtergt; lt;/activitygt;
那么啟動該Activity除了以上介紹的顯示方法外,我們還可以用以下方法
Intent intent = new Intent(quot;12345quot;); intent.addCategory(quot;android.intent.category.DEFAULTquot;); //可以不加,默認被加上 startActivity(intent);
隱式啟動是由action、category和data共同決定的,只有三者都滿足,該Activity才會被列入可處理列表,一般intent-filter包含一個action,可以包含多個category和data,所有category和某一個data滿足才行。如果你手機上多個應用同時擁有相同的intent-filter,那么就會出現一個應用列表供用戶選擇。
注:Android對待所有隱式Intent,默認它們已經具有了quot;android.intent.category.DEFAULTquot;,所以如果你想你的Activity被隱式調用,那一定需要在其intent-filter中加上該條category。不過入口Activity被quot;android.intent.action.MAINquot; 和quot;android.intent.category.LAUNCHERquot;標記的除外,雖然你也可以加上DEFAULT的category,但不是必須的
應用
學習了以上幾點后,我們來應用一下,做一個在不接入微信SDK的情況下的微信分享。你可以用apktool反編譯微信,然后通過看smali代碼和AndroidManifest文件,了解它規則后就能知道如何調用它的分享界面了。這里反編譯方法先不介紹了。經過分析,我們找到 ShareImgUI
類極為微信分享的朋友列表頁面,我們來看下它的AndroidManifest.xml中內容
lt;activity android:configChanges=quot;keyboardHidden|orientation|screenSizequot; android:icon=quot;@drawable/iconquot; android:name=quot;com.tencent.mm.ui.tools.ShareImgUIquot;gt; lt;intent-filter android:label=quot;@string/cquot;gt; lt;action android:name=quot;android.intent.action.SENDquot;/gt; lt;category android:name=quot;android.intent.category.DEFAULTquot;/gt; lt;data android:mimeType=quot;image/*quot;/gt; lt;data android:mimeType=quot;video/*quot;/gt; lt;data android:mimeType=quot;text/*quot;/gt; lt;data android:mimeType=quot;application/*quot;/gt; lt;/intent-filtergt; lt;intent-filter android:label=quot;@string/cquot;gt; lt;action android:name=quot;android.intent.action.SEND_MULTIPLEquot;/gt; lt;category android:name=quot;android.intent.category.DEFAULTquot;/gt; lt;data android:mimeType=quot;image/*quot;/gt; lt;/intent-filtergt; lt;/activitygt;
根據以上分析,對應分享代碼如下
Intent it = new Intent(Intent.ACTION_SEND); it.setComponent(new ComponentName(quot;com.tencent.mmquot;,quot;com.tencent.mm.ui.tools.ShareImgUIquot;)); it.putExtra(Intent.EXTRA_TEXT, quot;分享成功quot;); it.setType(quot;text/plainquot;); //可以不要 mActivity.startActivity(Intent.createChooser(it, quot;本機未安裝微信quot;));
相信上面的代碼大家很容易就能看明白,不過有人可能會迷惑,我們已經用顯示啟動了,為什么還要用action呢,這是因為微信在代碼里判斷了action,如果你不傳入這個action就無法分享。代碼的最后一行我們為了避免微信未安裝產生ActivityNotFoundException異常,用了Intent.createChooser來處理。分享圖片視頻理論上也都是可以的,但你需要具體分析下ShareImgUI的smali代碼,讓自己傳入的數據可以被微信接受就行。分享到朋友圈也一樣道理。
寫在后面
雖然上面分析了Activity啟動流程,但該流程只是簡化版,實際的啟動流程要復雜很多,涉及到很多類。雖是簡化版,但對我們理解有關Activity間跳轉的代碼足矣。后續也為大家能繼續深入源碼級別了解這些流程提供了一點引zi
Tags: Activity
文章來源:http://www.jianshu.com/p/4d261a086e71