Activity 启动流程


关注启动流程中的时机
1,Activity 创建
2,Application 创建
3,ContextImpl 初始化
4,attach() 方法
5,生命周期
6,窗体和管理器创建
7,布局初始化
8,窗体添加视图

一、启动方法

通过 Activity 的类名,显式启动,定义一个 Intent。

Intent intent = new Intent(this, XxxActivity);
startActivity(intent);

startActivity() 方法重载,最后调用 Activity 类 startActivityForResult() 方法,Intent 类封装启动意图,包含被启动对象的信息和数据。

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                                   @Nullable Bundle options) {
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);
        ...
    } else {
    }
}

Instrumentation 对象的 execStartActivity() 方法,实现 App 插件化时,可以 hook 该对象,拦截替换要启动的类名。

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    ...
    try {
        int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

ActivityManager 类 getService() 方法,获取 system_sever 进程 Ams 服务在本地的 binder 代理 IActivityManager。
通过代理的 startActivity()方法 ,进入Ams服务,请求参数 Bundle、IApplicationThread、Intent、requestCode 等,向 Ams 注册 Activity 组件。

ActivityThread 类和 Ams 服务的关系

1,ApplicationThread,ActivityThread 内部类,定义 Ams 服务回调 App 进程的业务接口,如 Activity 和 Service 启动/停止功能。
2,Context who.getBasePackageName(),当前发起者上下文包名,例如从 A 启动 B 组件时,who 是 A。
3,IBinder token,当前发起者内部 IBinder 对象,在组件启动的 attach() 方法赋值,通知 Ams 服务,发起者是谁,例如,当 Ams 服务回调 App 通知发起者暂停时,通过回传 App 进程的 token,可以查找执行暂停的组件。
在 Ams 服务,ActivityRecord 类记录 token,标识客户端一个 Activity 组件。

二、Ams 服务流程

跨进程调用 Ams 服务,即将组件 注册到 Ams,负责管理 Activity 栈结构。

Ams 服务流程( Activity 启动)

三、App 本地流程

客户端代理 IApplicationThread ,ApplicationThread 类的 scheduleTransaction() 方法。

@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    ActivityThread.this.scheduleTransaction(transaction);
}

ActivityThread 的 this 方法在父类中,即继承 ClientTransactionHandler 类。

void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
    sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}

ActivityThread 内部类 H 接收 EXECUTE_TRANSACTION 消息。

case EXECUTE_TRANSACTION:
    final ClientTransaction transaction = (ClientTransaction) msg.obj;
    mTransactionExecutor.execute(transaction);  
    ...
break;

TransactionExecutor 类的 execute() 方法,处理事务,参数 ClientTransaction 来自 Ams 服务。

public void execute(ClientTransaction transaction) {
    final IBinder token = transaction.getActivityToken();
    executeCallbacks(transaction); //处理LaunchActivityItem
    executeLifecycleState(transaction);//处理ResumeActivityItem
}
ClientTransaction 的 LaunchActivityItem 和 ResumeActivityItem

由 TransactionExecutor 类 execute() 方法 开始生命周期==>>

1,executeCallbacks() ==>> LaunchActivityItem execute()执行,ActivityThread 类 handleLaunchActivity() 方法 ==>onCreate()。

2,executeLifecycleState() ==>> cycleToPath()==>>ActivityThread 类handleStartActivity() 方法 ==>>onStart()。

3,executeLifecycleState() ==>> ResumeActivityItem execute()方法,ActivityThread 类 handleResumeActivity() 方法 ==>>onResume()。

LaunchActivityItem 类 execute() 方法。

@Override
public void execute(ClientTransactionHandler client, IBinder token,
                    PendingTransactionActions pendingActions) {
    //client即ActivityThread类
    ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
            mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
            mPendingResults, mPendingNewIntents, mIsForward,
            mProfilerInfo, client);
    client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
}

创建 ActivityClientRecord 本地记录,封装 Ams 回调数据,token 字段是在 Ams服务中 ActivityRecord 记录保存的唯一 appToken 标志。

ResumeActivityItem 类 execute()方法。

@Override
public void execute(ClientTransactionHandler client, IBinder token,
                    PendingTransactionActions pendingActions) {
    client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward,
            "RESUME_ACTIVITY");
}

client 即 ActivityThread 类,三个方法。

handleLaunchActivity(),
handleStartActivity(),
handleResumeActivity()。

Activity 启动本地流程图

1,handleLaunchActivity() 方法。

@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
                                     PendingTransactionActions pendingActions, Intent customIntent) {
    ...
    handleConfigurationChanged(null, null);
    //WindowManagerGlobal 初始化
    WindowManagerGlobal.initialize();
    //返回Activity对象
    final Activity a = performLaunchActivity(r, customIntent);
    if (a != null) {
        ...
    } else {
        try {
            //Activity对象未成功创建,通知Ams结束Activity的启动
            ActivityManager.getService()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
        }
    }
    return a;
}

ActivityThread 类 performLaunchActivity() 方法。


private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    //ActivityClientRecord封装的是Ams传来的信息。
    //获取本地记录ActivityClientRecord的ActivityInfo。
    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                Context.CONTEXT_INCLUDE_CODE);
    }
    //从Intent,获取组件Name,ComponentName
    ComponentName component = r.intent.getComponent();
    ...
    //创建ContextImpl对象,赋值给Activity
    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        //创建Activity实例 
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
    } catch (Exception e) {
    }
    try {
        //创建Application对象,赋值给Activity
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        if (activity != null) {
            ...
            appContext.setOuterContext(activity);
            //执行Activity的attach方法
            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, r.configCallback);
            if (r.isPersistable()) {
                //触发生命周期方法onCreate
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            r.activity = activity;
        }
        //绑定IBinder类型的token和ActivityClientRecord
        //Map数组<IBinder, ActivityClientRecord>
        //token 和本地记录保存在 Map 中,当 Ams 服务回调 App 进程的某个组件时,
        //根据 token 从 Map 中获取本地 ActivityClientRecord 从而定位到组件。
        mActivities.put(r.token, r);
    }  catch (Exception e) {
    }
    return activity;
}

该方法负责组件实例创建,生命周期方法开始。

Activity 组件创建

Activity 生命周期

在生命周期 onCreate() 方法,调用 setContentView() 方法,初始化 UI 布局。
setContentView() 初始化

初始化顶层视图 DecorView,PhoneWindow 窗体对象内部 mDecor 变量,根据布局资源 layout resId,解析视图对象,ViewGroup 类 addView() 方法添加,以顶层视图为根节点,构建树形结构。

2,handleStartActivity() 方法。

@Override
public void handleStartActivity(ActivityClientRecord r,
                                PendingTransactionActions pendingActions) {
    final Activity activity = r.activity;
    //activity是空,r状态是stop,activiity是mFinished,直接退出。
    //触发生命周期方法onStart()。
    activity.performStart("handleStartActivity");
    //触发Activity的onRestoreInstanceState方法
    if (pendingActions.shouldRestoreInstanceState()) {
        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方法
    ...
}

生命周期 onStart() 方法,必要时,执行 OnRestoreInstanceState()。

3,handleResumeActivity() 方法。

@Override
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
                                 String reason) {
    //生命周期onResume()方法
    final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
    final Activity a = r.activity;
    boolean willBeVisible = !a.mStartedActivity;
    if (r.window == null && !a.mFinished && willBeVisible) {
        //在attach()方法,已经为Activity创建了Window
        r.window = r.activity.getWindow();
        View decor = r.window.getDecorView();
        //此时DecorView不可见
        decor.setVisibility(View.INVISIBLE);
        ViewManager wm = a.getWindowManager();
        WindowManager.LayoutParams l = r.window.getAttributes();
        a.mDecor = decor;
        ...
        if (a.mVisibleFromClient) {
            if (!a.mWindowAdded) {
                a.mWindowAdded = true;
                //绑定View
                wm.addView(decor, l);
            } else {
                a.onWindowAttributesChanged(l);
            }
        }
    } else if (!willBeVisible) {
    }
    if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
        ...
        if (r.activity.mVisibleFromClient) {
            //让DecorView可见,即调用DecorView的setVisibility(View.VISIBLE)
            r.activity.makeVisible();
        }
    }
}

生命周期 onResume() 方法,组件可视化,组件绑定窗体和视图。

组件 Add Window 和 View
Window addView 视图
WindowManager 类 addView() 方法,
调用本地 WindowManagerImpl 类的 addView() 方法。

四、总结

框架层主要方法汇总:
1,createBaseContextForActivity(),创建 ContextImpl 。
2,Instrumentation # newActivity(),创建 Activity 实例。
3,LoadedApk # makeApplication(),首次创建 Application。
4,Activity # attach() ,赋值,窗体初始化,窗体管理器。
5,Instrumentation # callActivityOnCreate(),初始化 DecorView。
6,Activity # performStart(),开始活动。
7,Activity # performResume(),
8,WindowManager # addView(),


任重而道远

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

推荐阅读更多精彩内容