天天看点

Activity的启动过程--startActivity()

             当我们调用startActivity()启动一个Activity的时候,首先他会调到startActivityForResult()方法:

@Override
    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);
        }
    }
           

接下来看看 startActivityForResult()里都干了些什么:

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) {//只要关心mParent==null的情况就可以了
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            .........
        } else {
            ......
        }
    }
           

可以看到 startActivityForResult()里调用了 mInstrumentation.execStartActivity(),并且里面有个参数mMainThread.getApplicationThread()【其实就是ApplicationThread】,我们知道启动Activity最重要的其实就是客户端跟AMS通过Binder机制进行通信,所以客户端这边需要获得服务端AMS的代理(具体见下文),然后就可以调用AMS的方法,那么AMS是怎么调用客户端这边的方法呢?客户端的ApplicationThread(ActivityThread的内部类)是一个Binder,而在调用AMS方法的时候它被当做一个参数传过去了,这样子AMS也就获得了客户端这边的Binder代理。这样客户端和服务端这边就可以自如的进行通信,调用了。(Binder机制)

当然上面的这段只是简要的阐述了一下,接下来继续分析整个过程,先看看mInstrumentation.execStartActivity()里面做了什么:

这个里面其实就是获取AMS的代理(Binder机制),然后调用AMS里面的startActivity()方法。

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode) {
                                ......
        try {
        //ActivityManagerNative.getDefault()实际返回的是一个ActivityManagerProxy对象,也就是AMS的代理
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        null, 0, token, target != null ? target.mEmbeddedID : null,
                        requestCode, false, false);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }
        return null;
    }
           

至于他是如果获取到AMS的代理,可以看我的另一篇关于Binder机制的文章,其实就是在这个getDefault()里面,第一步先通过SMS(ServiceManager),即所有service的总管来获取到服务端Binder:

IBinder b=ServiceManager.getService("activity");

然后转化为AMS代理:

IActivityManager am=asInterface(b);

这样子就获得了AMS的代理。

接下来就看看AMS里面的startActivity()里面做什么:

AMS的startActivity()里面辗转调了好几个函数,最后调到realStartActivityLocked(),这个函数里面有一段代码:

app.thread.scheduleLaunchActivity(),并把AMS这边对这个Activity的记录各方面信息当做参数,这样客户端就能获取到Activity的各种信息即ActivityClientRecord

而这个app.thread的类型是IApplicationThread,而这个接口的实现者就是Activity里的ApplicationThread,而我们知道AMS里面已经获得客户端的ApplicationThread代理,所以他可以调用客户端ApplicationThread里面的scheduleLaunchActivity(),这样子,从服务端又回到了客户端中来了。

接下来看看Applicationthread.scheduleLaunchActivity()里面做了什么:

用一个Handler传一个消息到UI主线程,也就是ActivityThread

然后在Handler中接收消息,并调用handleLaunchActivity()【到了UI线程】。

handleLaunchActivity()中又调用了performLaunchActivity(),performLaunchActivity()里面最终完成了Activity的创建和启动过程。

而performLaunchActivity()里面主要干了一下几件事:

1.从ActivityClientRecord中获取待启动Activity的组件信息(ActivityClientRecord是刚刚AMS服务端调用前端的scheduleLaunchActivity()方法的时候当做参数传回来的)

2.创建Activity对象,通过Instrumentation的newActivity:

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

即通过ClassLoader来装载类并实例化对象。

3.通过LoadedApk的makeApplication方法来创建Application

4.创建ContextImpl对象,并通过Activity的attach()来完成一些重要的数据的初始化,并在这里面创建这个Activity对应的Window,并把这个Window和Activity建立联系,这样当Window接收到外部输入事件后就可以将事件传递给Activity。

5.调用mInstrumentation.callActivityOnCreate(),这里面调用了Activity的onCreate(),至此Activity正式启动。

下面简单总结一下:

先是从客户端开始:

startActivity()-->startActivityForResult()-->mInstrumentation.execStartActivity()  

到服务端AMS:

然后在mInstrumentation.execStartActivity()里面获取到AMS的代理(Binder机制),然后就到了服务端

AMS的startActivity()-->一系列辗转调用-->realStartActivityLocked()

然后在realStartActivityLocked()里通过客户端代理ApplicationThread来调用客户端的方法(BInder机制)

再回到客户端:

ApplictionThread里的scheduleLaunchActivity()-->handleLaunchActivity()-->performLaunchActivity()。

上面基本上就是Activity启动的全过程了。

继续阅读