Framework源碼面試之a(chǎn)ctivity啟動流程_第1頁
Framework源碼面試之a(chǎn)ctivity啟動流程_第2頁
Framework源碼面試之a(chǎn)ctivity啟動流程_第3頁
Framework源碼面試之a(chǎn)ctivity啟動流程_第4頁
Framework源碼面試之a(chǎn)ctivity啟動流程_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第Framework源碼面試之a(chǎn)ctivity啟動流程目錄引言Framework源碼面試:activity啟動流程1.1面試連環(huán)炮之說說Android的四種啟動模式1.2.面試連環(huán)炮之說說Intent標簽起什么作用呢?簡單說一說1.2.Android的啟動原理,他的流程是什么樣的1.2.1.進程A與AMS的交互過程

引言

今天在電腦上翻出了很久之前整理筆記Framework源碼面試,Flutter,以及一部分面試專題。拿出來溫習一下。

今天先講Framework源碼篇:

1.Framework源碼面試:Activity啟動流程

2.Framework源碼面試:Binder面試

3.Framework源碼面試:Handler面試

4.Framework源碼面試:事件分發(fā)機制

5.Framework源碼面試:onMeasure測量原理

6.Framework源碼面試:Android屏幕刷新機制

Framework源碼面試:activity啟動流程

面試的時候,面試官經(jīng)常同你隨便侃侃Activity的啟動模式,但Activity啟動牽扯的知識點其實很多,并非能單單用四個啟動模式就能概括的,

默認的啟動模式的表現(xiàn)會隨著IntentFlag的設置而改變,因此侃Activity啟動模式大多走流程裝逼,最多結合項目遇到的問題,隨便刁難一下面試者,并不太容易把控,也許最后,面試官跟面試者的答案都是錯了,

比如在Service中必須通過設置FLAG_ACTIVITY_NEW_TASK才能啟動Activity,這個時候啟動Activit會有什么樣的表現(xiàn)呢?就這一個問題,答案就要分好幾個場景:

Activity的taskAffinity屬性的Task棧是否存在如果存在,要看Activity是否存已經(jīng)存在于該Task如果已經(jīng)存在于該taskAffinity的Task,要看其是不是其rootActivity如果是其rootActivity,還要看啟動該Activity的Intent是否跟當前intent相等

不同場景,所表現(xiàn)的行為都會有所不同,再比如singleInstance屬性,如果設置了,大家都知道只有一個實例,將來再啟動會復用,但是如果使用Intent.FLAG_ACTIVITY_CLEAR_TASK來啟動,仍然會重建,并非完全遵守singleInstance的說明,還有不同F(xiàn)lag在疊加使用時候也會有不同的表現(xiàn),單一而論Activity啟動模式其實是很難的。本文也僅僅是涉及部分啟動模式及Flag,更多組合跟場景要自己看源碼或者實驗來解決了。

1.1面試連環(huán)炮之說說Android的四種啟動模式

standard

這是Activity的默認啟動模式,每次激活Activity的時候都會創(chuàng)建一個新的Activity實例,并放入任務棧中。

使用場景:基本絕大多數(shù)地方都可以用。

singleTop

這可能也是非常常用的launchMode了。如果在任務的棧頂正好存有該Activity的實例,則會通過調(diào)用onNewIntent()方法進行重用,否則就會同standard模式一樣,創(chuàng)建新的實例并放入棧頂。即便棧中已經(jīng)存在了該Activity的實例,也會創(chuàng)建新的實例,即:A-B-A,此時棧內(nèi)為A-B-A,但A-B-B,此時棧內(nèi)為A-B。一句話概述就是:當且僅當啟動的Activity和上一個Activity一致的時候才會通過調(diào)用onNewIntent()方法重用Activity。

使用場景:資訊閱讀類APP的內(nèi)容界面。

singleTask

這個launchMode專門用于解決上面singleTop的另外一種情況,只要棧中已經(jīng)存在了該Activity的實例,就會直接調(diào)用onNewIntent()方法來實現(xiàn)重用實例。重用時,直接讓該Activity的實例回到棧頂,并且移除之前它上面的所有Activity實例。如果棧中不存在這樣的實例,則和standard模式相同。即:A-B-C-D-B,此時棧內(nèi)變成了A-B。而A-B-C,棧內(nèi)還是A-B-C。

使用場景:瀏覽器的主頁面,或者大部分APP的主頁面。

singleInstance

在一個新棧中創(chuàng)建該Activity的實例,并讓多個應用共享該棧中的該Activity實例。一旦該模式的Activity實例已經(jīng)存在于某個棧中,任何應用再激活該Activity時都會重用該棧中的實例,是的,依然是調(diào)用onNewIntent()方法。其效果相當于多個應用共享一個應用,不管是誰激活,該Activity都會進入同一個應用中。但值得引起注意的是:singleInstance不要用于中間頁面,如果用戶中間頁面,跳轉(zhuǎn)會出現(xiàn)很難受的問題。這個在實際開發(fā)中我暫未遇到過,不過Android系統(tǒng)的來電頁面,多次來電均是使用的同一個Activity。

四種模式的背書式理解記憶講完了,你認為這樣就結束了嗎?

對,我也一度是這樣認為的。

1.2.面試連環(huán)炮之說說Intent標簽起什么作用呢?簡單說一說

我們除了需要知道在AndroidManifest.xml里面設置android:launchMode屬性,我們還需要了解下面這幾個Intent標簽的用法。

在Android中,我們除了在清單文件AndroidManifest.xml中配置launchMode,當然可以用Intent標簽說事兒。啟動Activity,我們需要傳遞一個Intent,完全可以通過設置Intent.setFlags(intflags)來設置啟動的Activity的啟動模式。

需要注意的是:通過代碼來設置Activity的啟動模式的方式,優(yōu)先級比清單文件設置更高。

FLAG_ACTIVITY_NEW_TASK這個標識會使新啟動的Activity獨立創(chuàng)建一個Task。FLAG_ACTIVITY_CLEAR_TOP這個標識會使新啟動的Activity檢查是否存在于Task中,如果存在則清除其之上的Activity,使它獲得焦點,并不重新實例化一個Activity,一般結合FLAG_ACTIVITY_NEW_TASK一起使用。FLAG_ACTIVITY_SINGLE_TOP等同于在launcherMode屬性設置為singleTop。

1.2.Android的啟動原理,他的流程是什么樣的

總的流程圖:

1.2.1.進程A與AMS的交互過程

此處以跨進程啟動Activity分析一下源碼流程:

①A調(diào)用startActivity時,需要與AMS交互,此時需要需要獲取到AMS的代理對象Binder也就是上圖的AMP,

通過ActivityManagerNative.getDefault()獲得,并調(diào)用AMP的startActivity方法,然后會通過mRemote.transact方法進行Binder通信,在AMS的onTransact方法里面會獲取到請求的Activity參數(shù)信息:

mRemote.transact(START_ACTIVITY_TRANSACTION,data,reply,0);

@Override

publicbooleanonTransact(intcode,Parceldata,Parcelreply,intflags){

switch(code){

caseSTART_ACTIVITY_TRANSACTION:{startActivity(app,callingPackage,intent,...)

②AMS里面的startActivity方法最主要會去調(diào)用startSpecificActivityLocked函數(shù),在此函數(shù)里面會去判斷目標進程是否已經(jīng)存在,并且目標向AMS注冊過它自己的ApplicationThread也就是上圖ATP代理對象,如果這兩個條件都滿足會去調(diào)用realStartActivityLocked方法,這個方法我們后面再看。如果上述條件不滿足時,會去調(diào)用mService.startProcessLocked(cessName,...)方法啟動進程。

startProcessLocked方法首先調(diào)用Process.start(android.app.ActivityThread,)方法會向Zygote發(fā)送一個啟動進程的請求,并告知Zygote進程啟動之后,加載ActivityThread這個類的入口main函數(shù),啟動完成后返回進程的pid,并向AMS的Handler發(fā)送一個延遲消息,為的是要求目標進程啟動后,10秒鐘內(nèi)需要向AMS報告,不然的話AMS就會清除目標進程的相關信息。Process.start方法會去調(diào)用startViaZygote(processClass,)函數(shù),這個函數(shù)主要做了兩件事,一件就是打開通往Zygote的Socket,第二件事就是通過Socket發(fā)送啟動進程參數(shù)。Zygote端主要邏輯是在runOnce函數(shù),函數(shù)內(nèi)調(diào)用Zygote.forkAndSpecialize(...)創(chuàng)建子進程,創(chuàng)建完成之后就分別在父進程和子進程里面做各自的事情.

父進程通過hanleParentProc(pid)把子進程的pid通過Socket發(fā)送給AMS

子進程調(diào)用handleChildProc函數(shù),做一些通用的初始化,比如啟用Binder機制;執(zhí)行應用程序的入口函數(shù),也就是ActivityThread的Main函數(shù).

ActivityThread的main函數(shù),里面會創(chuàng)建一個ActivityThread對象,并調(diào)用thread.attach(false),為的是向AMS報到,上面第一條里面有提到。attach方法里面,其實是一個跨進程的調(diào)用,首先通過

IActivityManagermgr=ActivityManagerNative.getDefault();

獲取到AMS的Binder代理對象,然后調(diào)用

mgr.attachApplication(mAppThread);

mAppThread是應用端的一個Binder對象ApplicationThread,也就是最上面一張圖的ATP,這樣AMS端就可以調(diào)用應用端了。

attachApplication方法里面,最主要有兩個方法,一個是通過傳入的ApplicationThread對象,調(diào)用bindApplication初始化Application對象,另一個就是通過

mStactSupervisor.attachApplicationLoacked(app);

初始化掛起的Activity對象。

在attachApplicationLoacked函數(shù)里,會調(diào)用

ActivityRecordhr=stack.topRunningActivityLocked(null);

?其中要明白AMS里面有兩個棧,一個是Launch桌面棧,一個就是非桌面棧mFocusedStack,此處的stack就是mFocusedStack,它會將棧頂?shù)腁ctivityRecord返回出來,我們的目標Activity早就放置在了棧頂,只是一直沒有初始化。然后調(diào)用方法,來啟動Activity

?如果我們不是啟動另外一個進程,而是同一進程,那么這第二大部分就不會存在了,而是直接調(diào)用realStartActivityLocked方法。

realStartActivityLocked(hr,app,true,true);

寫到這里是不是有很多碼牛的小伙伴們已經(jīng)堅持不下去了。還剩最后幾個步驟

①realStartActivityLocked函數(shù)會調(diào)用app.thread.scheduleLaunchActivity(newIntent(ent),...);也就是通過之前注冊的Binder對象ATP,調(diào)用scheduleLaunchActivity函數(shù),在scheduleLaunchActivity函數(shù)里面:

ActivityClientRecordr=newActivityClientRecord();

sendMessage(H.LAUNCH_ACTIVITY,r);

封裝了一個ActivityClientRecord消息,然后丟到主線程的Handler(mH)里。

②在主線程里面

finalActivityClientRecordr=(ActivityClientRecord)msg.obj;

r.packageInfo=getPackageInfoNoCheck(...);

handleLaunchActivity(r,null);

getPackageInfoNoCheck函數(shù)主要是用來生成一個LoadedApk對象,它用來保存我們的apk信息,因為后面我們需要一個ClassLoader去加載Apk里面的Activity類,所以這里提前準備好。

③handleLaunchActivity里面分為兩個部分,一個是performLaunchActivity函數(shù),一個是handleResumeActivity函數(shù)。

performLaunchAc

溫馨提示

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

評論

0/150

提交評論