【Android源码系列】Activity启动源码解析

一、前言

最近看《Android开发艺术探索》大多涉及到源码解析,仅仅看书有点云里雾里,于是配合着源码一起看感觉清晰许多。网上很多推荐source insight看源码,下来之后体验感觉一般,还不如AS直接看。老罗有专门的源码查看教学,但是需要Linux(Ubuntu)/MAC机器,暂时没条件以后考虑(老罗讲的比较深入,值得长期跟)。总之还是在AS里看(求推荐),强烈推荐浏览本文时和着源码。

二、源码解析

1、startActivityForResult
启动activity的方法最后都会走到startActivityForResult里。

这里写图片描述
这里调用了Instrumentation的execStartActivity方法,我们直接跟进。

这里写图片描述
在Instrumentation里调用了ActivityManagerNative的getDefault()方法,getDefault返回了一个IActivityManager对象。

这里写图片描述
是一个单例对象,看到asInterface很熟悉(不熟悉的可以参考我的另一篇博客Android多进程IPC机制——binder原理探索
IActivityManager其实就是binder接口,查看ActivityManagerNative代码发现他其实就是扮演正常IPC接口IActivityManager里的stub角色,这样的话需要一个实现这个stub接口的类来实现startActivity方法。
没错,他就是ActivityManagerService,我们进到startActivity,发现他直接丢给了startActivityAsUser,在里面又调用了ActivityStackSupervisor的startActivityMayWait方法,这里的跳转都很简单,我就不贴代码了。下面我们来看看startActivityMayWait。

final int startActivityMayWait(//参数省略) {
//我们只关心如何启动,部分检查判断代码省略,千万不要企图搞懂每一句代码的意思,有兴趣的话回头再过来看

int res = startActivityLocked(caller, intent, resolvedType, aInfo,voiceSession, voiceInteractor, resultTo, resultWho,requestCode, callingPid, callingUid, callingPackage,realCallingPid, realCallingUid, startFlags, options,componentSpecified, null, container, inTask);

}

这里调用了startActivityLocked,而startActivityLocked里面又调用了startActivityUncheckedLocked,这个方法非常长,当时我是看晕了。这里我贴上关键代码。
这里写图片描述
经过一系列判断,调用了resumeTopActivitiesLocked方法,resumeTopActivitiesLocked里转给了ActivityStack的resumeTopActivityLocked方法。(这里其实可能调用ActivityStack的startActivityLocked方法,不过最终都会走到resumeTopActivityLocked)。在resumeTopActivityLocked内部又调用自己的resumeTopActivityInnerLocked方法,然后又回调了ActivityStackSupervisor的startSpecificActivityLocked方法:

这里写图片描述
直接走到realStartActivityLocked里,然后又一次的IPC通信,接口是IApplicationThread

这里写图片描述
这里调用了接口的scheduleLaunchActivity方法,和上一次一样,我们找到实现类ApplicationThread(是ActivityThread的内部类),以及他的scheduleLaunchActivity方法:

        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, 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;

            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

这个方法把传过来的参数包装成ActivityClientRecord ,通过sendMessage传出去,我们来看看这个sendMessage。

这里写图片描述

这里调用了mH的sendMessage方法,mH其实就是一个handler,我们看他如何处理数据:

这里写图片描述
在里面调用了方法handleLaunchActivity。

 private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//省略部分代码
 Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);

            if (!r.activity.mFinished && r.startsNotResumed) {
                try {
                    r.activity.mCalled = false;
                    mInstrumentation.callActivityOnPause(r.activity);
                    // part of stopping the activity.
                    if (r.isPreHoneycomb()) {
                        r.state = oldState;
                    }
                    if (!r.activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPause()");
                    }

                } catch (SuperNotCalledException e) {
                    throw e;

                } catch (Exception e) {
                    if (!mInstrumentation.onException(r.activity, e)) {
                        throw new RuntimeException(
                                "Unable to pause activity "
                                + r.intent.getComponent().toShortString()
                                + ": " + e.toString(), e);
                    }
                }
                r.paused = true;
            }
        } else {
            // If there was an error, for any reason, tell the activity
            // manager to stop us.
            try {
                ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
            } catch (RemoteException ex) {
                // Ignore
            }
        }

}

终于,我们看见了activity的实例

Activity a = performLaunchActivity(r, customIntent);

在这个方法里调用了activity的attach,以及生命周期oncreate。其他生命周期在上面代码里实现。

到这里,我们就理通了Activity的启动过程,主要还是利用IPC传递信息。
最后我推荐大家看源码时一定要做笔记,可以的话最好画图来帮助自己理清思路,不然会完全懵逼的。我目前使用startUML来画时序图,下面贴一张图。

这里写图片描述

怎么样,看到这张图感觉是不是整个流程清晰无比了?

哈哈,最后最后求查看源码方式,AS虽然勉强可以,但是也会经常找不到类很蛋疼。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值