亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Framework源碼面試之a(chǎn)ctivity啟動(dòng)流程

 更新時(shí)間:2022年09月23日 11:34:37   作者:初一十五不吃飯  
這篇文章主要為大家介紹了Framework源碼面試之a(chǎn)ctivity啟動(dòng)流程實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

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

今天先講Framework源碼篇:

1.Framework源碼面試:Activity啟動(dòng)流程

2.Framework源碼面試:Binder面試

3.Framework源碼面試:Handler面試

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

5.Framework源碼面試:onMeasure測(cè)量原理

6.Framework源碼面試:Android屏幕刷新機(jī)制

Framework源碼面試:activity啟動(dòng)流程

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

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

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

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

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

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

  • standard

這是 Activity 的默認(rèn)啟動(dòng)模式,每次激活 Activity 的時(shí)候都會(huì)創(chuàng)建一個(gè)新的 Activity 實(shí)例,并放入任務(wù)棧中。

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

  • singleTop

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

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

  • singleTask

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

使用場(chǎng)景:瀏覽器的主頁(yè)面,或者大部分 APP 的主頁(yè)面。

  • singleInstance

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

四種模式的背書式理解記憶講完了,你認(rèn)為這樣就結(jié)束了嗎?

對(duì),我也一度是這樣認(rèn)為的。

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

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

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

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

  • FLAG_ACTIVITY_NEW_TASK 這個(gè)標(biāo)識(shí)會(huì)使新啟動(dòng)的 Activity 獨(dú)立創(chuàng)建一個(gè) Task
  • FLAG_ACTIVITY_CLEAR_TOP 這個(gè)標(biāo)識(shí)會(huì)使新啟動(dòng)的 Activity 檢查是否存在于 Task 中,如果存在則清除其之上的 Activity,使它獲得焦點(diǎn),并不重新實(shí)例化一個(gè) Activity,一般結(jié)合 FLAG_ACTIVITY_NEW_TASK 一起使用。
  • FLAG_ACTIVITY_SINGLE_TOP 等同于在 launcherMode 屬性設(shè)置為 singleTop。

1.2.Android 的啟動(dòng)原理,他的流程是什么樣的

總的流程圖:

1.2.1.進(jìn)程A與AMS的交互過程

此處以跨進(jìn)程啟動(dòng)Activity分析一下源碼流程:

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

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

mRemote.transact(START_ACTIVITY_TRANSACTION,data,reply,0);
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags){
      switch(code){
   case START_ACTIVITY_TRANSACTION:{        startActivity(app,callingPackage,intent,...)
   }
 }
}

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

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

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

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

  • ActivityThreadmain函數(shù),里面會(huì)創(chuàng)建一個(gè)ActivityThread對(duì)象,并調(diào)用thread.attach(false),為的是向AMS報(bào)到,上面第一條里面有提到。
  • attach方法里面,其實(shí)是一個(gè)跨進(jìn)程的調(diào)用,首先通過
IActivityManager mgr = ActivityManagerNative.getDefault();

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

mgr.attachApplication(mAppThread); 

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

  • attachApplication方法里面,最主要有兩個(gè)方法,一個(gè)是通過傳入的ApplicationThread對(duì)象,調(diào)用bindApplication初始化Application對(duì)象,另一個(gè)就是通過
mStactSupervisor.attachApplicationLoacked(app);

初始化掛起的Activity對(duì)象。

  • attachApplicationLoacked函數(shù)里,會(huì)調(diào)用
ActivityRecord hr = stack.topRunningActivityLocked(null);

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

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

realStartActivityLocked(hr,app,true,true);

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

realStartActivityLocked函數(shù)會(huì)調(diào)用app.thread.scheduleLaunchActivity(new Intent(r.intent),...);也就是通過之前注冊(cè)的Binder對(duì)象ATP,調(diào)用scheduleLaunchActivity函數(shù),在scheduleLaunchActivity函數(shù)里面:

ActivityClientRecord r = new ActivityClientRecord();
...
sendMessage(H.LAUNCH_ACTIVITY,r);

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

②在主線程里面

final ActivityClientRecord r = (ActivityClientRecord)msg.obj ;
r.packageInfo = getPackageInfoNoCheck(...);
handleLaunchActivity(r,null);

getPackageInfoNoCheck 函數(shù)主要是用來生成一個(gè)LoadedApk對(duì)象,它用來保存我們的apk信息,因?yàn)楹竺嫖覀冃枰粋€(gè)ClassLoader去加載Apk里面的Activity類,所以這里提前準(zhǔn)備好。

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

performLaunchActivity

Activity activity = mInstrumentation.newActivity(...);
//返回之前創(chuàng)建好的
Application app = r.packageInfo.makeApplication(false,mInstrumentation);
//生成ContextImpl
Context appContext = createBaseContextForActivity(r,activity);
//給activity綁定上下文和一些初始化的工作,如createPhoneWindow
activity.attach(appContext,...);
mInstrumentation.callActivityOnCreate(activity,r.state); //生命周期的OnCreate
activity.performStart();    //生命周期的OnStart
return activity

handleResumeActivity

-> r.activity.performResume()     
   -> mInstrumentation.callActivityOnResume(this);
     -> activity.onResume()

以上就是Framework源碼面試之a(chǎn)ctivity啟動(dòng)流程的詳細(xì)內(nèi)容,更多關(guān)于Framework activity啟動(dòng)流程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 九宮圖比較常用的多控件布局(GridView)使用介紹

    九宮圖比較常用的多控件布局(GridView)使用介紹

    GridView跟ListView都是比較常用的多控件布局,而GridView更是實(shí)現(xiàn)九宮圖的首選,下面與大家分享下GridView用法,感興趣的朋友可以參考下哈
    2013-06-06
  • Android 管理Activity中的fragments

    Android 管理Activity中的fragments

    為了管理Activity中的fragments,需要使用FragmentManager,為了得到它,需要調(diào)用Activity中的getFragmentManager()方法,接下來詳細(xì)介紹,感興趣的朋友可以了解下哦
    2013-01-01
  • Android ListView萬能適配器實(shí)例代碼

    Android ListView萬能適配器實(shí)例代碼

    本文主要介紹Android ListView萬能適配器,這里整理了詳細(xì)的資料及實(shí)現(xiàn)代碼,以及實(shí)現(xiàn)效果圖,有需要的小伙伴可以參考下
    2016-09-09
  • Android手機(jī)屏幕敲擊解鎖功能代碼

    Android手機(jī)屏幕敲擊解鎖功能代碼

    Android手機(jī)支持敲擊屏幕解鎖,敲擊屏幕解鎖是一項(xiàng)很實(shí)用的功能,本文以android平臺(tái)為例使用java代碼實(shí)現(xiàn)Android手機(jī)屏幕敲擊解鎖功能,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧
    2016-07-07
  • Android中刪除Preference詳解

    Android中刪除Preference詳解

    這篇文章主要介紹了Android中刪除Preference詳解,很多時(shí)候刪除Preference總會(huì)失敗,本文著重分析刪除失敗的原因,需要的朋友可以參考下
    2015-01-01
  • AndroidManifest.xml中含蓋的安全問題詳解

    AndroidManifest.xml中含蓋的安全問題詳解

    這篇文章主要介紹了AndroidManifest.xml中含蓋的安全問題,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • 基于android布局中的常用占位符介紹

    基于android布局中的常用占位符介紹

    下面小編就為大家分享一篇基于android布局中的常用占位符介紹,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • Android連接服務(wù)器端的Socket的實(shí)例代碼

    Android連接服務(wù)器端的Socket的實(shí)例代碼

    這篇文章主要介紹了Android連接服務(wù)器端的Socket的實(shí)例代碼,需要的朋友可以參考下
    2017-05-05
  • Android?studio下載安裝使用SVN的方法

    Android?studio下載安裝使用SVN的方法

    在AndroidStudio中開發(fā)版本控制,除了Git就是SVN,和Eclipse不同,Android Studio沒有提供單獨(dú)的插件,只能和SVN客戶端關(guān)聯(lián)使用,這篇文章主要介紹了Android?studio使用SVN的方法,需要的朋友可以參考下
    2022-09-09
  • Android實(shí)現(xiàn)懸浮窗全系統(tǒng)版本

    Android實(shí)現(xiàn)懸浮窗全系統(tǒng)版本

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)懸浮窗全系統(tǒng)版本,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11

最新評(píng)論