startActivity源码探索

本篇文章是基于API25源码

知识

  • Activity:这个大家都熟悉,startActivity方法的真正实现在Activity中
  • Instrumentation:用来辅助Activity完成启动Activity的过程
  • ActivityThread(包含ApplicationThread + ApplicationThreadNative + IApplicationThread):真正启动Activity的实现都在这里

正文:

Activity.startActivity

先从入口startActivity开始罗,其实最后调用的还是

   public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

  public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {

            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) {
               onResume()
                mStartedActivity = true;
            }
            cancelInputsAndStartExitTransition(options);
    }

可以看,最后到了startActivityForResult里面,Instrumentation隆重出场,关于它是从哪里来的,是在Activity#attach()中作为参数传进来的。

Instrumentation.execStartActivity是真正打开activity的方法

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;
        try {
        ...省略了Intent传值和是否存在这个activity部分代码
            int result = ActivityManagerNative.getDefault()
                .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;
    }

可以看出,这里出现了两个关键人物(IApplicationThread,ActivityManagerNative),IApplicationThread只是一个接口,核心代码在ActivityManagerNative中,先别着急,还要再说一个方法

checkStartActivityResult:

这个方法是专门抛异常的,它会对结果进行检查,如果无法打开activity,
则抛出诸如在配置文件没有找到activity就会发生ActivityNotFoundException类似的各种异常
有兴趣的可以自己看看源码,这里没啥好说的.

接下来看看ActivityManagerNative~

ActivityManagerNative.startActivity

   public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }

看方法内部,你会发现,我擦,怎么全是binder呢,接下去呢,去哪了?这里是AIDL,实现了IActivityManager接口。

同时看IApplicationThread是继承了IInterface,你想到了啥?

在我们平时实现跨进程IPC调用的时候是不是要继承这个接口,所以我们基本可以判定ActivityManagerNative其实就是一个跨进程调用的类。

是由远端的ActivityManagerService实现startActivity

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);
        // TODO: Switch to user app stacks here.
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null);
    }

ActivityStarter mActivityStarter,25的源码变成了他,当然里面内容是没怎么变的.

mActivityStarter.startActivityMayWait()

看看里面写了啥,内容有点长,我直接贴关键代码


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

继续,我们在找到startActivityLocked方法,他的代码量更多,同样,我们还是找关键的来看

ActivityStarter.startActivityLocked

       try {
            mService.mWindowManager.deferSurfaceLayout();
            err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                    true, options, inTask);
        } finally {
            mService.mWindowManager.continueSurfaceLayout();
        }

然而经过很长的代码寻找,跳转最后到了ActivityThread….方法中调用了sendMessage

      sendMessage(H.LAUNCH_ACTIVITY, r);

嗯,没错里面有个handler,我直接看handleMessage 方法吧

        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");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;

        }

里面还有其他msg的操作,我就不带着看,代码很长…

我们上面调用了handleLaunchActivity这个方法,接着我们在继续找这个方法,随便查看一下他的源码

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);  
        …………………………  
            r.paused = true;  
        }  
    } else {  
        …………………………  
    }  
}  

我们看到performLaunchActivity返回一个Activity,之前估计我们很多都不知道Activity究竟是怎么初始化的,这回大家终于明白了吧,我们随便看一下他的源码

performLaunchActivity

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {  
    …………………………  
    Activity activity = null;  
    try {  
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();  
        //创建Activity  
        activity = mInstrumentation.newActivity(  
                cl, component.getClassName(), r.intent);  
      …………………………  

    try {  
        //创建Application  
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);  
        …………………………  
        if (activity != null) {  
            Context appContext = createBaseContextForActivity(r, activity);  
            CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());  
            Configuration config = new Configuration(mCompatConfiguration);  
            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "  
                    + r.activityInfo.name + " with config " + config);  
            //调用Activity的attach方法,这个我们在前面讲的时候也多次提及  
            activity.attach(appContext, this, getInstrumentation(), r.token,  
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,  
                    r.embeddedID, r.lastNonConfigurationInstances, config);  

            …………………………  
            int theme = r.activityInfo.getThemeResource();  
            if (theme != 0) {  
               // 设置主题  
                activity.setTheme(theme);  
            }  

            //调用Activity的OnCreate方法,  
            mInstrumentation.callActivityOnCreate(activity, r.state);  
           …………………………  
            if (!r.activity.mFinished) {  
                //调用Activity的onStart方法  
                activity.performStart();  
                r.stopped = false;  
            }  
            if (!r.activity.mFinished) {  
                if (r.state != null) {  
                   //调用Activity的OnRestoreInstanceState方法  
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);  
                }  
            }  
           …………………………  
    return activity;  
}  

Activity是通过Instrumentation这个类创建的,我们可以看一下,代码非常简短

public Activity newActivity(ClassLoader cl, String className,  
        Intent intent)  
        throws InstantiationException, IllegalAccessException,  
        ClassNotFoundException {  
    return (Activity)cl.loadClass(className).newInstance();  
}  

我们可以看到performLaunchActivity方法调用了Activity的onCreate方法和onStart方法

然后我们在看上面的handleLaunchActivity方法在调用完performLaunchActivity方法的时候又调用了handleResumeActivity方法。我们也可以顺便看一下他的源码

handleResumeActivity

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,  
        boolean reallyResume) {  
    …………………………  
    //调用了Activity的performResume方法,然后执行onResume方法  
    ActivityClientRecord r = performResumeActivity(token, clearHide);  

    if (r != null) {  
        final Activity a = r.activity;  
        …………………………  
        boolean willBeVisible = !a.mStartedActivity;  
        …………………………  
        if (r.window == null && !a.mFinished && willBeVisible) {  
            r.window = r.activity.getWindow();  
            View decor = r.window.getDecorView();  
            decor.setVisibility(View.INVISIBLE);  
            ViewManager wm = a.getWindowManager();  
            WindowManager.LayoutParams l = r.window.getAttributes();  
            a.mDecor = decor;  
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;  
            l.softInputMode |= forwardBit;  
            if (a.mVisibleFromClient) {  
                a.mWindowAdded = true;  
                wm.addView(decor, l);  
            }  
            …………………………  
            r.activity.mVisibleFromServer = true;  
            mNumVisibleActivities++;  
            if (r.activity.mVisibleFromClient) {  
                //调用Activity的makeVisible方法  
                r.activity.makeVisible();  
            }  
        }  
        …………………………  
}  

总结:

  1. Activity中最终到startActivityForResult()
  2. ->接着是Instrumentation出场,调用execStartActivity()和checkStartActivityResult()(这是在启动了Activity之后判断Activity是否启动成功,例如没有在AM中注册那么就会报错)
  3. ->这里使用AIDL发送信息如:ActivityManagerNative.getDefault().startActivity(),接受者也就是ActivityManagerService-AMS
  4. AMS#startActivity,然后经过经过源码几次周转到了ActivityThread
  5. ->ActivityThread#handleLaunchActivity()(接收内部类H的消息,ApplicationThread线程发送LAUNCH_ACTIVITY消息给H)
  6. ->最终在ActivityThread#performLaunchActivity()中实现Activity的启动完成了以下几件事:
    1. 从传入的ActivityClientRecord中获取待启动的Activity的组件信息
    2. 创建类加载器,使用Instrumentation#newActivity()加载Activity对象
    3. 调用LoadedApk.makeApplication方法尝试创建Application,由于单例所以不会重复创建。
    4. 创建Context的实现类ContextImpl对象,并通过Activity#attach()完成数据初始化和Context建立联系,因为Activity是Context的桥接类,
    5. 最后就是创建和关联window,让Window接收的事件传给Activity,在Window的创建过程中会调用ViewRootImpl的performTraversals()初始化View。
    6. Instrumentation#callActivityOnCreate()->Activity#performCreate()->Activity#onCreate().onCreate()中会通过Activity#setContentView()调用PhoneWindow的setContentView()更新界面。

源码很复杂,其中看着看着就会迷路了,因为有着以前搞插件化的基础,大致知道AMS的一些类是干什么的,所幸还能探索到最后…

结语:

其实startActivity,到最后还是在ActivityThread中完成的,而具体点就是拿到ClassLoader,Instrumentation去拿ClassLoader去加载一个Class,继续获取Application也是通过Classloader进行创建的,当然有的话,就不会创建。然后创建ContextImpl,他就是Context,后面在调用attach…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值