探索7.x, 全面解析Activity启动框架 (2)

欢迎Follow我的GitHub, 关注我的简书, 博客目录.

Activity

本文的合集已经编著成书,高级Android开发强化实战,欢迎各位读友的建议和指导。在京东即可购买:https://item.jd.com/12385680.html

Android

本文是探索Activity启动源码的第二篇, 其余参考第一篇.

第一篇的流程图:

流程图

第一篇已经探索至关键位置, 即ActivityStackSupervisor的realStartActivityLocked方法, 方法如其名, 从此开始, 才是真正地(Real)启动(Start). Let's start!


ActivityManagerService

ActivityStackSupervisor#realStartActivityLocked:

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
        boolean andResume, boolean checkConfig) throws RemoteException {

    // 当屏幕方向修改时, 推迟恢复, 防止冗余启动Activity.
    if (checkConfig) {
        Configuration config = mWindowManager.updateOrientationFromAppTokens(
                mService.mConfiguration,
                r.mayFreezeScreenLocked(app) ? r.appToken : null);
        mService.updateConfigurationLocked(config, r, false, true /* deferResume */);
    }

    // 将进程描述符(ProcessRecord)设置入Activity描述符(ActivityRecord)
    r.app = app;
    app.waitingToKill = null; // 避免在后台被杀死
    r.launchCount++; // 增加启动次数
    r.lastLaunchTime = SystemClock.uptimeMillis(); // 最新启动时间

    // 当Activity描述符不在进程的Activity列表中, 将Activity添加入进程的Activity列表
    int idx = app.activities.indexOf(r);
    if (idx < 0) {
        app.activities.add(r);
    }
    // AMS更新进程描述符为最少最新使用(LRU).
    mService.updateLruProcessLocked(app, true, null); 
    // ...
    try {
        // ...
        // 远程调用ApplicationThread的scheduleLaunchActivity
        app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
                task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
        // ...
    } catch (RemoteException e) {
        // ...
    }
    // ...
    return true;
}

ActivityRecord即Activity描述符(变量r), 含有被启动的Activity信息; ProcessRecord即进程描述符(变量app), 含有当前应用的进程信息.
app.thread类型是IApplicationThread, 通过IApplicationThread的代理ApplicationThreadProxy, 远程调用ApplicationThread的scheduleLaunchActivity方法, ApplicationThread是IApplicationThread的最终实现.

启动Activity再次AMS(ActivityManagerService)通过远程调用(Binder)交给应用进程(ActivityThread)处理. ApplicationThread是ActivityThread的私有类.

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) {
    // ...
    // 即来自客户端(AMS)的Activity描述符
    ActivityClientRecord r = new ActivityClientRecord();

    // 将AMS的Activity描述符, 转换为当前进程的Activity描述符
    r.token = token;
    // ...

    // 封装, 发送启动消息给H类处理, 并传递Activity描述符
    sendMessage(H.LAUNCH_ACTIVITY, r);
}

sendMessage是重载方法, 最终调用H类处理数据.

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
    // ...
    // 最终由H类(Handler)处理数据
    mH.sendMessage(msg);
}

将启动Activity交给ActivityThread的Handler H类处理.

private class H extends Handler {
 public void handleMessage(Message msg) {
    switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                ActivityClientRecord r = (ActivityClientRecord)msg.obj;
                // 设置Activity描述符的包信息
                r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
                // 至此, 完成启动Activity已经由AMS交给当前应用, 在当前应用中启动Activity.
                handleLaunchActivity(r, null);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            } break;
        }
    }
}   

启动Activity, 先由当前进程, 通过ActivityManagerNative#getDefault#startActivity方法, 交给AMS处理, AMS管理Activity的Stack和Task, 并设置Activity描述符(Record); 再通过app.thread#scheduleLaunchActivity方法, 继续交给当前进程处理.

AMS切换当前线程的流程图:

流程图

ActivityThread

ActivityThread#handleLaunchActivity:

handleLaunchActivity调用performLaunchActivity方法, 继续执行启动, 在成功后, 调用handleResumeActivity方法, 执行显示Activity.

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        // 因为当前进程正在活跃, 所以跳过在后台中执行GC.
        unscheduleGcIdler();
        // ...

        // 确保使用最近的环境配置
        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);

        // 在创建Activity前, 初始化WindowManagerGlobal, 即WindowManagerService
        WindowManagerGlobal.initialize();

        // 执行启动Activity
        Activity a = performLaunchActivity(r, customIntent);

        // 在启动成功后, 处理恢复Activity
        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            // 恢复Activity
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
            // ...
            }
        } else {
            // 如果发生错误, 则AMS停止启动Activity
            try {
                ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }

ActivityThread#performLaunchActivity:

performLaunchActivity方法是Activity启动的核心:

  1. 获取Activity的组件信息(ComponentName);
  2. 根据组件使用反射创建Activity(newActivity);
  3. 将Activity绑定(attach)Application和BaseContext;
  4. 相继调用onCreate, onStart, onRestoreInstanceState, onPostCreate等方法.
  5. 放入Activity列表(Map)中统一管理, token是key.
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        // 通过应用信息, 兼容信息, 从PMS, 获取Activity的包信息
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                Context.CONTEXT_INCLUDE_CODE);
    }

    // 获取组件信息
    ComponentName component = r.intent.getComponent();
    if (component == null) {
        component = r.intent.resolveActivity(
            mInitialApplication.getPackageManager());
        r.intent.setComponent(component);
    }

    // 当指定Activity时, 使用包名和类名创建组件
    if (r.activityInfo.targetActivity != null) {
        component = new ComponentName(r.activityInfo.packageName,
                r.activityInfo.targetActivity);
    }

    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        // 通过反射, 使用ClassLoader创建Activity
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        // ...
    } catch (Exception e) {
        // ...
    }

    try {
        // 使用单例模式, 创建Application
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        // ...
        if (activity != null) {
            // 创建Activity的上下文BaseContext
            Context appContext = createBaseContextForActivity(r, activity);
            // ...
            // 将Activity绑定上下文appContext, 和应用app
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window);
            // ...
            // 设置主题
            int theme = r.activityInfo.getThemeResource();
            if (theme != 0) {
                activity.setTheme(theme);
            }

            activity.mCalled = false; // 判断执行是否成功, 成功会置true
            // 调用Activity的onCreate方法.
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            // ...
            // 调用Activity的onStart方法.
            if (!r.activity.mFinished) {
                activity.performStart();
                r.stopped = false;
            }
            // 调用Activity的onRestoreInstanceState方法.
            if (!r.activity.mFinished) {
                if (r.isPersistable()) {
                    if (r.state != null || r.persistentState != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                r.persistentState);
                    }
                } else if (r.state != null) {
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                }
            }
            // 调用Activity的onPostCreate方法.
            if (!r.activity.mFinished) {
                activity.mCalled = false; // 判断执行是否成功, 成功会置true
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state,
                            r.persistentState);
                } else {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
                }
                // ...
            }
        }
        r.paused = true;

        // 将Activity放入ActivityThread的Activity数组中统一管理.
        mActivities.put(r.token, r);

    } // ...
    return activity;
}

onPostCreate: Called when activity start-up is complete (after onStart() and onRestoreInstanceState(Bundle) have been called). Applications will generally not implement this method; it is intended for system classes to do final initialization after application code has run.
在调用时, 表明Activity已经完全启动, 只剩下显示(onResume).

通过分析performLaunchActivity, 我们也更加清晰Activity的生命周期, 顺序如下, onCreate, onStart, onRestoreInstanceState, onPostCreate. 注意, onStart是Activity处理; 其余三个是Instrumentation处理, 支持继承重写相应方法, 自行处理.


至此, Activity已经完全启动, 并调用相应的生命周期方法.

OK, that's all! Enjoy it!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容