Activity的启动过程第三篇

作者: b496178cdc84 | 来源:发表于2016-09-20 09:29 被阅读97次

    上一篇 ,我们分析到了这里
    //这里是真正打开Activity的地方
    //这个ActivityManagerNative.getDefault()是AMS的代理对象,调用startActivity来将activity启动起来

                int result  = ActivityManagerNative.getDefault()
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, null, options);
    

    通过这个我们ActivityManagerNative.getDefault的源码,我们也知道,这里实际上是获取了AndroidManagerService的代理对象。,AndroidManagerProxy,OK我们继续看下面。
    继续深入到ActivityManagerNative.getDefault().startActivity()的方法中

    class ActivityManagerProxy implements IActivityManager{
        public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
                String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                int startFlags, String profileFile,
                ParcelFileDescriptor profileFd, 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);
            data.writeString(profileFile);
            if (profileFd != null) {
                data.writeInt(1);
                profileFd.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);
            }
            //这个remote是个Ibinder类型,负责进程通信,也就是和ActivityManagerService进行进程通信
            mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
            reply.readException();
            int result = reply.readInt();
            reply.recycle();
            data.recycle();
            return result;
        }
    }
    

    这里面主要做的事情,就是,把上面传回来的参数,写入Parcel的data中去,并发送一个类型为START_ACTIVITY_TRANSACTION的进程通信请求。这里面我们关注3个参数,caller ,Intent,和resultTo,参数caller指向了Launch组件所运行进程的ApplicationThread对象,参数Intent 包含了要启动Activity组件的详细信息,参数resultTo指向了AMS内部的ActivityRecord(这个类的作用是维护对应activity组件的运行信息)对象,它里面保存了Launcher的详细信息。OK到这里为止,都是在Launcher里面执行的,我们在回顾一下总的过程。

    1、Laucher组件 首先向AMS(AndroidManagerService)发送一个启动Mainactivity的请求, 这个请求是进程间通信的。
    2、AMS首先将要启动的MainActivity组件的信息保留起来,然后向Laucher组件发送一个进入终止状态的进程通信。
    3、然后,Laucher组件会接收到AMS发来的中止请求,进入中止状态, 然后再向AMS发送消息,告诉AMS 我已经进入中止状态了,你请继续做你的是事情,这样AMS就能继续进行启动Aty的操作。
    4、由于MainAty的启动是在Lauther程序中启动的,Lauther中止了,程序应用进程也就不存在了,然后AMS就会新启动一个应用进程。
    5、新的应用进程启动后,就会告诉AMS 我(新的应用进程)已经启动好了,然后发一个通信请求给AMS。
    6、接收到新应用进程发来的通信后,AMS就会把第二步保留的组件信息 传递给新的进程,然后新的进程就可以靠这些信息去启动MainAty。

    到目前为止,我们已经分析了上面的前3个步骤。以上3个步骤都是Launcher和AMS交互的过程,然后来做一个小节。

    前三步小节:
    首先,Launcher会在PackageManagerService中寻找Main组件信息,然后将信息与对应APP图标关联起来,并将组件信息保存起来,然后就会调用 Activity的startActivity方法,之后又会调用Instrument的execStartActivity方法,Instrument主要作用于监控APP与系统之间的通信,在执行过execStartActivity方法后,Launcher就把Instrument(Activity的成员)传递给AMS,AMS接收到这个对象,就获取到了Launcher的信息,下一步就让Launcher进入停止状态。最后,也就是这篇提到的,Launcher通过发送mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);这个类型的进程通信,把信息传给AMS,通知Launcher已经进入终止状态,然后接下来的启动过程交给AMS。

    相关文章

      网友评论

        本文标题:Activity的启动过程第三篇

        本文链接:https://www.haomeiwen.com/subject/kwynettx.html