android小白進(jìn)階系列----activity啟動(dòng)分析

前言

曾經(jīng)我也有迷茫過,android開發(fā)過一定經(jīng)驗(yàn)届囚,我還要干嘛?學(xué)其他語言是尖?經(jīng)過幾經(jīng)思想斗爭意系,我選擇了專攻android之路,在我android未達(dá)到高層級(jí)別饺汹,我不會(huì)花太多精力去學(xué)其他蛔添,畢竟android是我飯碗,連飯碗都丟了兜辞,還能指望你能學(xué)好其他的迎瞧?那么問題來了怎么專攻?對android底層的了解逸吵,無疑對你上層代碼使用能更加的 輕車熟路凶硅、避免bug。所有才有了源碼分析系列的博客
“好記性不如爛筆頭”扫皱,在看過很多android的FrameWork源碼足绅,過幾天再回想一下,總是零零散散韩脑,不成知識(shí)體系氢妈,自己動(dòng)手一步一記錄源碼分析的過程。同時(shí)也給一些想進(jìn)一步了解android開發(fā)一個(gè)方向扰才。讓我們共同努力。

怎么做

1厕怜、工具:android studio
2衩匣、雙擊Shift查找api文件


查找源碼文件

3、由外到內(nèi)的分析粥航,一層一層的解刨

activity啟動(dòng)分析

    //kotlin 語言
    val intent = Intent(this@MainActivity, Main2Activity::class.java)
    this.startActivity(intent)

相信大家對這段代碼用得輕車熟路了琅捏,我們用它啟動(dòng)一個(gè)activity。Ctrl+鼠標(biāo)左擊startActivity递雀。往里面接著看

    @Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }
    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            startActivityForResult(intent, -1);
        }
    }

跳轉(zhuǎn)到了Activity.java的startActivity(Intent intent)柄延,細(xì)看的有兩個(gè)重載函數(shù),核心代碼在帶有兩個(gè)參數(shù)的函數(shù)中的startActivityFoResult(Intent intent, int requestCode, @Nullable Bundle options)

  • intent:包含啟動(dòng)activity的信息。
  • requestCode:請求標(biāo)識(shí)字段(略過)
  • options:存儲(chǔ)一些啟動(dòng)activity的參數(shù)搜吧,比如切換動(dòng)畫市俊,一些附帶數(shù)據(jù)等等,詳細(xì)的可以看ActivityOptions類滤奈。常用的我們默認(rèn)為null摆昧。
  public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {//mParent=Activity (1)
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                mStartedActivity = true;
            }
            cancelInputsAndStartExitTransition(options);
        } else {//activity不為null (2)
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {    
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

我們先從(2)處開始分析,默認(rèn)activity不為null蜒程。最后都調(diào)用startActivityFromChild()绅你。

 public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent,
            int requestCode, @Nullable Bundle options) {
        //對options進(jìn)行封裝,options為null就采用系統(tǒng)默認(rèn)
        options = transferSpringboardActivityOptions(options);
        //生成ActivityResult對象昭躺,里面包含resultCode和resultData
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, child,
                intent, requestCode, options);
        //執(zhí)行發(fā)送消息ActivityResult
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, child.mEmbeddedID, requestCode,
                ar.getResultCode(), ar.getResultData());
        }
        //取消輸入功能和動(dòng)畫的執(zhí)行
        cancelInputsAndStartExitTransition(options);
    }

接下來忌锯,我們看下如何生成ActivityResult對象。方法Instrumentation.execStartActivity()

public ActivityResult execStartActivity(                                              
        Context who, IBinder contextThread, IBinder token, Activity target,           
        Intent intent, int requestCode, Bundle options) {                             
    IApplicationThread whoThread = (IApplicationThread) contextThread;                
    Uri referrer = target != null ? target.onProvideReferrer() : null;                
    if (referrer != null) {                                                           
        intent.putExtra(Intent.EXTRA_REFERRER, referrer);                             
    }                                                                                 
    if (mActivityMonitors != null) {                                                  
        synchronized (mSync) {                                                        
            //遍歷ActivityMonitor,看是否存在這個(gè)Activity                                       
            final int N = mActivityMonitors.size();                                   
            for (int i=0; i<N; i++) {                                                 
                final ActivityMonitor am = mActivityMonitors.get(i);                  
                if (am.match(who, null, intent)) {                                    
                    am.mHits++;                                                       
                    //如果當(dāng)該monitor阻塞activity啟動(dòng),也就是目標(biāo)Activity無法打開就直接return                                         
                    if (am.isBlocking()) {                                            
                        return requestCode >= 0 ? am.getResult() : null;              
                    }                                                                 
                    //如果存在就跳出循環(huán)                                                       
                    break;                                                            
                }                                                                     
            }                                                                         
        }                                                                             
    }                                                                                 
    try {                                                                             
        intent.migrateExtraStreamToClipData();                                        
        intent.prepareToLeaveProcess(who);                                            
        //真正的startActivity的方法领炫,其實(shí)核心功能在whoThread的scheduleLaunchActivity完成的              
          int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);                
        //用于檢查打開Activity異常的方法偶垮,比如常見的Activity沒在AndroidManifest的話,                       
        // 會(huì)拋出“...have you declared this activity in your AndroidManifest.xml?”異常     
        checkStartActivityResult(result, intent);                                     
    } catch (RemoteException e) {                                                     
        throw new RuntimeException("Failure from system", e);                         
    }                                                                                 
    return null;   

ActivityManager.getService().startActivity()方法才是啟動(dòng)activity的核心驹吮,內(nèi)部代碼會(huì)通過清單文件緩存池中獲取對應(yīng)activity针史,然后返回result標(biāo)記,如果沒有就會(huì)拋出have you declared this activity in your AndroidManifest.xml?”異常 碟狞。如果大家有了解過插件化開發(fā)原理啄枕,滴滴的VirtualApk方法就是從這里入手。通過ActivityManagerProxy 動(dòng)態(tài)代理類族沃,使得將插件化的清單文件緩存進(jìn)去频祝。首先進(jìn)去ActivityManager里面看一下getService方法


    /**
     * @hide
     */
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }
 
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;      //ActivityManagerService
                }

這里可能有人找不到對應(yīng)的startActivity方法在哪里,我這里是有安卓源碼通過搜索得到ActivityManagerService中有startActivity并且有addService()

 public void setSystemProcess() {
        try {
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);

到這里根本的startActivity方法終于找到了脆淹,讓我們直達(dá)內(nèi)部方法常空,一看究竟。ActivityManagerService.startActivity方法

  @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }
  @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
        //這里啟動(dòng)ActivityStarter類中的startActivityMayWait()
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null,
                "startActivityAsUser");
    }

startActivityMayWait是個(gè)非常長的方法盖溺,里面處理的邏輯我們現(xiàn)在可以暫時(shí)不看漓糙,如何需要查看intent和flags的相關(guān)轉(zhuǎn)換時(shí)再仔細(xì)分析。

final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult,
            Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
            TaskRecord inTask, String reason) {
        //省略
 
            final ActivityRecord[] outRecord = new ActivityRecord[1];
            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor,
                    resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,
                    reason);
 
            Binder.restoreCallingIdentity(origId);
        //省略
       }

int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, TaskRecord inTask, String reason) {
        //省略
 
        mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
                inTask);
 
        //省略
        return mLastStartActivityResult != START_ABORTED ? mLastStartActivityResult : START_SUCCESS;
    }

這里由于跳轉(zhuǎn)太多烘嘱,如果一步一步跟進(jìn)昆禽,最后會(huì)來到一個(gè)ApplicationThread中的scheduleLaunchActivity方法

  @Override
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
 
            updateProcessState(procState, false);
 
            ActivityClientRecord r = new ActivityClientRecord();
 
            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;
 
            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;
 
            r.startsNotResumed = notResumed;
            r.isForward = isForward;
 
            r.profilerInfo = profilerInfo;
 
            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);
 
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

這里發(fā)送了一個(gè)Handle消息,如果對H.LAUNCH_ACTIVITY進(jìn)行查找蝇庭,會(huì)來到ActivityThread類中的一段代碼

  public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");//見名知意醉鳖,啟動(dòng)activity
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;

  private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        //省略
 
        Activity a = performLaunchActivity(r, customIntent);
 
        //省略
    }

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        //調(diào)用activity的onCreate()
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                //省略
 
        return activity;
    }

各個(gè)類的作用
以下僅供參考

Launcher:用戶看到的桌面,只是一個(gè)Activity
Instrumentation:在應(yīng)用代碼初始化之前運(yùn)行哮内,用于監(jiān)控應(yīng)用與系統(tǒng)的交互盗棵,管理著Application、Activity的生命周期
ActivityManagerService:處于安卓架構(gòu)的Framework層,運(yùn)行在SystemServer進(jìn)程中纹因,調(diào)度系統(tǒng)中的所有Activity喷屋,AMS會(huì)決定哪個(gè)Activity可以啟動(dòng)
ActivityStarted:決定了Activity是如何啟動(dòng)的,包含了intent和flags如何被轉(zhuǎn)換并且與任務(wù)棧相關(guān)聯(lián)的所有邏輯
ActivityStackSupervisor:Activity的棧管理類
ActivityStack:聲明和管理一個(gè)activity任務(wù)棧的狀態(tài)
ActivityThread:每一個(gè)應(yīng)用都有對應(yīng)的ActivityThread辐怕,進(jìn)程創(chuàng)建時(shí)會(huì)執(zhí)行ActivityThread的Main方法
ApplicationThread:主要負(fù)責(zé)與AMS交互

上一張流程圖逼蒙,加深印象


圖片來源于網(wǎng)絡(luò)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市寄疏,隨后出現(xiàn)的幾起案子是牢,更是在濱河造成了極大的恐慌,老刑警劉巖陕截,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驳棱,死亡現(xiàn)場離奇詭異,居然都是意外死亡农曲,警方通過查閱死者的電腦和手機(jī)社搅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乳规,“玉大人形葬,你說我怎么就攤上這事∧旱模” “怎么了笙以?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長冻辩。 經(jīng)常有香客問我倡怎,道長蹬昌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任城须,我火速辦了婚禮簇捍,結(jié)果婚禮上哮针,老公的妹妹穿的比我還像新娘玛瘸。我一直安慰自己媒峡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布钧敞。 她就那樣靜靜地躺著蜡豹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪犁享。 梳的紋絲不亂的頭發(fā)上余素,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天豹休,我揣著相機(jī)與錄音炊昆,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛凤巨,可吹牛的內(nèi)容都是我干的视乐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼敢茁,長吁一口氣:“原來是場噩夢啊……” “哼佑淀!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起彰檬,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤伸刃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后逢倍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捧颅,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年较雕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了碉哑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡亮蒋,死狀恐怖扣典,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情慎玖,我是刑警寧澤贮尖,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站凄吏,受9級(jí)特大地震影響远舅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜痕钢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一图柏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧任连,春花似錦蚤吹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拱她,卻和暖如春二驰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背秉沼。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工桶雀, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留矿酵,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓矗积,卻偏偏與公主長得像全肮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子棘捣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容