Android應(yīng)用程序內(nèi)部啟動Activity過程(startActivity)的源代碼分析_第1頁
Android應(yīng)用程序內(nèi)部啟動Activity過程(startActivity)的源代碼分析_第2頁
Android應(yīng)用程序內(nèi)部啟動Activity過程(startActivity)的源代碼分析_第3頁
Android應(yīng)用程序內(nèi)部啟動Activity過程(startActivity)的源代碼分析_第4頁
Android應(yīng)用程序內(nèi)部啟動Activity過程(startActivity)的源代碼分析_第5頁
已閱讀5頁,還剩13頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、上文介紹了 Android應(yīng)用程序的啟動過程,即應(yīng)用程序默認 Activity的啟動過程,一般來說,這種默認 Activity是在新的進程和任務(wù)中啟動的;本文將繼續(xù)分析在應(yīng)用程序內(nèi)部啟動非默認Activity的過程的源代碼,這種非默認Activity 一般是在原來的進程和任務(wù)中啟動的。這里,我們像上一篇文章Android應(yīng)用程序啟動過程源代碼分析一樣,采用再上一篇文章Android應(yīng)用程序的Activity啟動過程簡要介紹和學(xué)習(xí)計劃所舉的例子來分析在應(yīng)用程序內(nèi)部啟動非默認Activity的過程。在應(yīng)用程序內(nèi)部啟動非默認Activity的過程與在應(yīng)用程序啟動器Launcher中啟動另外一個應(yīng)用程

2、序的默認Activity的過程大體上一致的,因此,這里不會像上文 Android應(yīng)用程序啟動過程源代碼分析一樣詳 細分析每一個步驟,我們著重關(guān)注有差別的地方。回憶一下Android應(yīng)用程序的Activity啟動過程簡要介紹和學(xué)習(xí)計劃 一文所用的應(yīng)用程序 Activity, 它包含兩個Activity,分別是MainActivity和SubActivity,前者是應(yīng)用程序的默認 Activity,后者是非默認 Activity。MainActivity啟動起來,通過點擊它界面上的按鈕,便可以在應(yīng)用程序內(nèi)部啟動SubActivity。我們先來看一下應(yīng)用程序的配置文件AndroidManifest.

3、xml ,看看這兩個 Activity是如何配置的:view plain1.v?xml version ="1.0"encoding ="utf-8"?>2.<ma ni festxmln s:a ndroid=" ndroid"3.package ="sh yu o.activity"4.an droid:vers ion Code="1"5.android:versionName="1.0" >6.<applicati onan droid:ic

4、on="drawable/ico n"an droid:label= "stri ng/app_ name">7.<activityan droid:n ame='.Mai nActivity"8.an droid:label= "stri ng/app_ name">9.vinten t-filter>10.<act ionan droid:n ame ="a ndroid.i nten t.acti on. MAIN"/>11.vcategoryan dro

5、id:n ame ="a ndroid.i nten t.category.LAUNCHER"/>12.</inten t-filter>13.v/activity>14.vactivityan droid:n ame='.SubActivity"15.an droid:label= "stri ng/sub_activity">16.vinten t-filter>17.vact ionan droid:n ame="shyu o.activity.subactivity"/&g

6、t;18.vcategoryan droid:n ame="a ndroid.i nten t.category.DEFAULT"/>19.</inten t-filter>20.v/activity>21.v/applicati on>22.</ma nifest>這里可以很清楚地看到,MainActivity被配置成了應(yīng)用程序的默認 Activity,而SubActivity可以通過名稱 “shy.luo.activity.subactivity 隱式地啟動,我們來看一下 src/shy/luo/activity/MainAct

7、ivity.java文件的內(nèi)容,可以清楚地看到 SubActivity是如何隱式地啟動的:view plain1. public class Main Activityexte nds Activityimpleme nts On ClickListe ner 2. 3.3. Override4. public void on Click(View v) 5. if (v.equals(startButton) 6. Intent intent =new lntent("sh yu o.activity.subactivity");7. startActivity(i nt

8、e nt);8. 9. 10. 這里,首先創(chuàng)建一個名稱為“shy.luo.activity.subactivity的Intent",然后以這個Intent為參數(shù),通過調(diào)用startActivity 函數(shù)來實現(xiàn)隱式地啟動SubActivity。有了這些背景知識后,我們就來看一下SubActivity啟動過程的序列圖:«円frl m 円點擊查看大圖與前面介紹的MainActivity啟動過程相比,這里少了中間創(chuàng)建新的進程的步驟;接下來,我們就詳細分析一下SubActivity與MainActivity啟動過程中有差別的地方,相同的地方請參考 Android應(yīng)用程序啟動 過程源代

9、碼分析一文。Step 1. Activity.startActivity這一步與上一篇文章 Android應(yīng)用程序啟動過程源代碼分析的Step 2大體一致,通過指定名稱“ shy.luo.activity.subactivity來告訴應(yīng)用程序框架層,它要隱式地啟動SubActivity。所不同的是傳入的參數(shù)intent 沒有 lntent.FLAG_ACTIVITY_NEW_TASK標志,表示這個 SubActivity 和啟動它的 MainActivity 運行在同一個Task中。Step 2. Activity.startActivityForResult這一步與上一篇文章Android應(yīng)

10、用程序啟動過程源代碼分析Step 3. Instrumentation.execStartActivity這一步與上一篇文章Android應(yīng)用程序啟動過程源代碼分析的 Step 3 一致。的 Step 4 一致。Step 4. ActivityManagerProxy.startActivity這一步與上一篇文章 Android應(yīng)用程序啟動過程源代碼分析的Step 5 一致。Step 5. ActivityManagerService.startActivity這一步與上一篇文章 Android應(yīng)用程序啟動過程源代碼分析的 Step 6 一致。Step 6. ActivityStack.sta

11、rtActivityMayWait這一步與上一篇文章 Android應(yīng)用程序啟動過程源代碼分析的Step 7 一致。Step 7. ActivityStack.startActivityLocked這一步與上一篇文章 Android應(yīng)用程序啟動過程源代碼分析的Step 8 一致。Step 8. ActivityStack.startActivityUncheckedLocked |這一步與上一篇文章Android應(yīng)用程序啟動過程源代碼分析的Step 9有所不同,主要是當前要啟動的Activity與啟動它的Activity是在同一個Task中運行的,我們來詳細看一下。這個函數(shù)定義在framewo

12、rks/base/services/java/com/android/server/am/ActivityStack.java文件中:view plain.5.6.public class ActivityStack final int startActivityU ncheckedLocked(ActivityRecord r,ActivityRecord sourceRecord, Uri gran tedUriPermissi grantedMode,boolean onlylfNeeded,boolea n doResume) 1.12

13、.9.50.final Intent intent = r.i ntent;final int calli ngUid = raun chedFromUid;int laun chFlags = inten t.getFlags();if (sourceRecord = null ) else if (sourceRecord.launchMode = ActivityInfo.

14、LAUNCH_SINGLE_INSTANCE) else if (r.launchMode = ActivityInfo.LAUNCH_SINGLE_INSTANCE0) if (r.resultTo !=null && (launchFlags&lntent.FLAG_ACTIVITY_NEW_TASK) !=boolea n addi ngToTask =falseif (launchFlags&lntent.FLAG_ACTIVITY_NEW_TASK) !=0 &&(lau nchFlags&lnten t.FLAG_ACTIVI

15、TY_MULTIPLE_TASK) =0)| r.lau nchMode = Activit yin fo.LAUNCH_SINGLE_TASK| r.lau nchMode = ActivityI nfo.LAUNCH_SINGLE_INSTANCE) if (r.packageName != null ) / If the activity being laun ched is the same as the one curre ntly / at the top, then we need to check if it should only be launched / on ce.Ac

16、tivityRecord top = topR unningNon DelayedActivityLocked( no tTop);if (top != null && r.resultTo =null ) if (top.realActivity.equals(r.realActivity) else boolea n n ewTask = false0.61./ Should this be con sidered a new task?if (r.resultTo =null && !addingTo

17、Task&& (lau nchFlags&lnten t.FLAG_ACTIVITY_NEW_TASK) !=0) else if (sourceRecord !=null ) / An existing activity is starting this new activity, so we want/ to keep the new one in the same task as the one that is start ing/ it.8.r.task = sourceRecord.task;else

18、5.沒有設(shè)置,在配置文件于是它就默認標準模式,即startActivityLocked(r, n ewTask, doResume);return START_SUCCESS;76.77. 這里,參數(shù) intent 的標志位 lntent.FLAG_ACTIVITY_NEW_TASK AndriodManifest.xml 中,SubActivity 也沒有配置啟動模式 launchMode , Activitylnfo.LAUNCH_MULTIPLE,因此,下面 if 語句不會執(zhí)行:view plain1. if (launchFlags&lntent.FLAG_A

19、CTIVITY_NEW_TASK) !=0 &&2. (lau nchFlags&ln te nt.FLAG_ACTIVITY_MULTIPLE_TASK) =0)3. | r.lau nchMode = Activityl nfo.LAUNCH_SINGLE_TASK4. | r.lau nchMode = Activityl nfo.LAUNCH_SINGLE_INSTANCE) 5于是,變量 addingToTask 為 false繼續(xù)往下看:1. if (r.packageName !=null ) 2. /If the activity being laun

20、ched is the same as the one curre ntly3. / at the top, then we need to check if it should only be launched4. / on ce.5. ActivityRecord top = topR unningNon DelayedActivityLocked( no tTop);6. if (top != null && r.resultTo =null ) 7. if (top.realActivity.equals(r.realActivity) 8. 9. 10. 11.12.

21、 這里看一下當前要啟動的 Activity是否就是當前堆棧頂端的Activity,如果是的話,在某些情況下,就不用再重新啟動了。函數(shù)topRunningNonDelayedActivityLocked 返回當前堆棧頂端的Activity,這里即為 MainActivity,而當前要啟動的 Activity為SubActivity,因此,這二者不相 等,于是跳過里面的if語句。接著往下執(zhí)行:view plain1. / Should this be con sidered a new task?2. if (r.resultTo =null && !addingToTask3.

22、&& (lau nchFlags&ln te nt.FLAG_ACTIVITY_NEW_TASK) !=0) 45.5. else if (sourceRecord !=null ) 78. / An existi ng activity is start ing this new activity, so we want9. / to keep the new one in the same task as the one that is start ing10. / it.11. r.task = sourceRecord.task;1213.14. else 15

23、16.前面說過參數(shù)intent的標志位lntent.FLAG_ACTIVITY_NEW_TASK沒有設(shè)置,而這里的sourceRecord 即為當前執(zhí)行啟動Activity操作的Activity,這里即為 MainActivity,因此,它不為 null,于是于MainActivity所屬的Task設(shè)置到r.task中去,這里的r即為SubActivity??吹竭@里,我們就知道 SubActivity 要和 MainActivity 運行在同一個 Task中了,同時,變量 newTask的值為false。最后,函數(shù)進 入startActivityLocked(r, newTask, doRes

24、ume)進一步處理了。這個函數(shù)同樣是定義在 frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中:view plain..9.publicclass ActivityStack private final void startActivityLocked(ActivityRecord r, boo

25、lea n doResume) final int NH = mHistory.size();boolea n n ewTask,int addPos = -1;if (!newTask) / If starting in an existing task, find where that is.boolean startIt = true ;for (int i = NH- 1; i >=0; i-) ActivityRecord p = (ActivityRecord)mHistory.get(i);if (p.finishing) con ti nue ;if (p.task =

26、r.task) / Here it is! Now, if this is n ot yet visible to the/ user, the n just add it without start in g; it will/ get started whe n the user n avigates back to it.addPos = i+1 ;if (!startIt) mHistory.add(addPos, r);r.inHistory =true ;r.task .n umActivities+;mService.mWi ndowMa nager.addAppToke n(

27、addPos, r, r.task.taskId,r.i nfo.scree nOrie ntati on, r.fullscree n);if (VALIDATE_TOKENS) mService.mWi ndowMa nager.validateAppToke ns(mHistory);return ;break ;if (p.fullscreen) startIt =false ;4.45./ Slot the activity into the history stack and proceed46.mHistory.add(addPos, r);47.r.inHi

28、story =true ;48.r.fron tOITask = n ewTask;49.r.task .n umActivities+;3.if (doResume) 54.resumeTopActivityLocked(null );8.59.60.這里傳進來的參數(shù) newTask為false , doResume 為true。當newTask為false,表示即將要啟動 的Activity是在原有的Task運行時,如果這個原有的Task當前對用戶不可見時,這時候就不需要繼續(xù)執(zhí)行下去了,因為即使把這個 Activity啟動起來,用戶也看不到,還不如先

29、把它保存起來,等到下次這個Task 對用戶可見的時候,再啟動不遲。這里,這個原有的 Task,即運行MainActivity的Task當前對用戶是可 見的,因此,會繼續(xù)往下執(zhí)行。接下去執(zhí)行就會把這個SubActivity通過mHistroy.add(addPos, r)添加到堆棧頂端去,然后調(diào)用resumeTopActivityLocked進一步操作。Step 9. ActivityStack.resumeTopActivityLocked這一步與上一篇文章 Android應(yīng)用程序啟動過程源代碼分析的Step 10 一致。但是要注意的是,執(zhí)行到這個函數(shù)的時候,當前處于堆棧頂端的Activity

30、為SubActivity , ActivityStack的成員變量 mResumedActivity 指向 MainActivity 。Step 10. ActivityStack.startPausingLocked這一步與上一篇文章 Android應(yīng)用程序啟動過程源代碼分析的Step 11 一致。從這里開始,ActivityManagerService 通知 MainActivity 進入 Paused 狀態(tài)。Step 11. ApplicationThreadProxy.schedulePauseActivity這一步與上一篇文章 Android應(yīng)用程序啟動過程源代碼分析的Step 12

31、 一致。Step 12. ApplicationThread.schedulePauseActivity這一步與上一篇文章Android應(yīng)用程序啟動過程源代碼分析的 Step 13 一致。Step 13. ActivityThread.queueOrSendMessage這一步與上一篇文章 Android應(yīng)用程序啟動過程源代碼分析的 Step 14 一致。Step 14. H.handleMessage這一步與上一篇文章Android應(yīng)用程序啟動過程源代碼分析的 Step 15 一致。Step 15. ActivityThread.handlePauseActivity這一步與上一篇文章And

32、roid應(yīng)用程序啟動過程源代碼分析的 Step 16一致。Step 16. ActivityManagerProxy.activityPaused這一步與上一篇文章Android應(yīng)用程序啟動過程源代碼分析的 Step 17一致。2.2.Step 17. ActivityManagerService.activityPaused這一步與上一篇文章Android應(yīng)用程序啟動過程源代碼分析的 Step 18一致。2.2.Step 18. ActivityStack.activityPaused這一步與上一篇文章Android應(yīng)用程序啟動過程源代碼分析的 Step 19一致。Step 19. Acti

33、vitySpletePauseLocked這一步與上一篇文章Android應(yīng)用程序啟動過程源代碼分析的 Step 20 一致。執(zhí)行到這里的時候,MainActivity就進入Paused狀態(tài)了,下面就開始要啟動SubActivity 了。Step 20. ActivityStack.resumeTopActivityLokced這一步與上一篇文章Android應(yīng)用程序啟動過程源代碼分析的 Step 21 一致。Step 21. ActivityStack.startSpecificActivityLocked會調(diào)用mService.startProcessLocked來創(chuàng)建一個新的進程來啟動新

34、的Activity,我們來看一下這個函數(shù)的實現(xiàn),這個函數(shù)定義在view plainframeworks/base/services/java/com/android/server/am/ActivityStack.java文件中:這一步與上一篇文章Android應(yīng)用程序啟動過程源代碼分析的Step 22就有所不同了,這里,它不1. public class ActivityStack .private final void startSpecificActivityLocked(ActivityRecord r,6.boolea n an dResume,boolea n che

35、ckC on fig) 7./ Is this activity's application already running?8.ProcessRecord app = mService.getProcessRecordLocked(cessName,9.r.i nfo.applicati onln fo.uid);3.if (app !=null&& app.thread !=null ) 14.try 15.realStartActivityLocked(r, app, an dResume, checkC on fig);16.ret

36、urn ;17.catch (RemoteExcepti on e) 7.28.這里由于不是第一次啟動應(yīng)用程序的Activity ( MainActivity是這個應(yīng)用程序第一個啟動的Activity ),所以下面語句:view plain1. ProcessRecord app = mService.getProcessRecordLocked(cessName,2. n fo.applicati onln fo.uid);取回來的app不為null。在上一篇文章 Android應(yīng)用程序啟動過程源代碼分析中,我們介紹過,在Ac

37、tivity應(yīng)用程序中的 AndroidManifest.xml 配置文件中,我們沒有指定 application 標簽的process屬性, 于是系統(tǒng)就會默認使用 package的名稱,這里就是"shy.luo.activity" 了。每一個應(yīng)用程序都有自己的 uid, 因此,這里uid + process 的組合就可以創(chuàng)建一個全局唯一的ProcessRecord。這個 ProcessRecord 是在前面啟動MainActivity時創(chuàng)建的,因此,這里將它取回來,并保存在變量app中。注意,我們也可以在AndroidManifest.xml 配置文件中指定 SubAct

38、ivity 的process屬性值,這樣 SubActivity 就可以在另外一個 進程中啟動,不過很少有應(yīng)用程序會這樣做,我們不考慮這種情況。這個app的thread也是在前面啟動 MainActivity時創(chuàng)建好的,于是,這里就直接調(diào)用 realStartActivityLocked函數(shù)來啟動新的 Activity 了,新的Activity的相關(guān)信息都保存在參數(shù)r中了。Step 22. ActivityStack.realStartActivityLocked這一步與上一篇文章 Android應(yīng)用程序啟動過程源代碼分析的Step 28 一致。Step 23. ApplicationThre

39、adProxy.scheduleLaunchActivity這一步與上一篇文章Android應(yīng)用程序啟動過程源代碼分析的 Step 29 一致。Step 24. ApplicationThread.scheduleLaunchActivity這一步與上一篇文章Android應(yīng)用程序啟動過程源代碼分析的 Step 30 一致。Step 25. ActivityThread.queueOrSendMessage這一步與上一篇文章Android應(yīng)用程序啟動過程源代碼分析的 Step 31 一致。Step 26. H.handleMessage這一步與上一篇文章Android應(yīng)用程序啟動過程源代碼分析

40、的 Step 32 一致。Step 27. ActivityThread.handleLaunchActivity這一步與上一篇文章 Android應(yīng)用程序啟動過程源代碼分析Step 28. ActivityThread.performLaunchActivity這一步與上一篇文章 Android應(yīng)用程序啟動過程源代碼分析ClassLoader 里面加載的類就是 shy.luo.activity.SubActivity 了。的 Step 33 一致。的Step 34 一致,不過,這里要從Step 29. SubAcitiviy.onCreate這個函數(shù)定義在 packages/experimental/Activity/src/shy/luo/activity/SubActivity.java文件中,這是我們自定義的app工程文件:view plain1. public class SubActivityexte nds Activit

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論