Activity 源码分析

启动一个activity大体可以分为2种情况,比如A启动B,

1,A和B在同一个进程中

2,A和B分属于2个不同的apk,在2个不同的进程中。

以下论述的是第2种情况,即A和B位于不同的进程,那么会涉及到2次跨进程通信,第一次是A进程和AMS服务所在进程进行通信,

第二次是AMS服务所在进程与B进程进行通信。

1, 客户端

客户端启动Activity流程图如下,

当客户端调用startActivity时,会直接调用Activity.java的对应函数

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);//无结果返回
        }
    }

startActivityForResult方法如下,

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle 
options) {
        if (mParent == null) {
            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());
            }
            •••
        }
    }

一般启动activity时, mParent都为空,

什么是Instrumentation?Instrumentation是android系统中启动Activity的一个实际操作类,也就是说Activity在应用进程端

(客户端)的启动实际上就是Instrumentation执行的,那么为什么说是在应用进程端的启动呢?实际上acitivty的启动分为应用

进程端的启动和SystemServer服务进程端的启动的,多个应用进程相互配合最终完成了Activity在系统中的启动的,而在应用

进程端的启动实际的操作类就是Intrumentation来执行的。

execStartActivity方法如下,

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        android.util.SeempLog.record_str(377, intent.toString());
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
       •••
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            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;
    }

execStartActivity方法的7个参数如下:

this,为启动Activity的对象;

contextThread,为Binder对象,是主进程的context对象;

token,也是一个Binder对象,指向了服务端一个ActivityRecord对象;

target,为启动的Activity;

intent,启动的Intent对象;

requestCode,请求码;

options,是否返回处理结果的参数;

 

ActivityManagerNative.getDefault()方法最后得到的其实是ActivityManagerNative 的代理类ActivityManagerProxy,

其实就是AMS在客户端的代理,然后通过binder机制进行通信。

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对象,把所有需要的参数封装成Parcel对象,然后调用transact(),向AMS发送数据进行通信。

START_ACTIVITY_TRANSACTION 是一个标记。

需要注意的是这些流程都运行于客户端进程之中。

2, 服务端

通过数据传输之后就会调用SystemServer进程的ActivityManagerService的startActivity方法,

调用流程图如下,


ActivityManagerNative的onTransact方法如下,

public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
        case START_ACTIVITY_TRANSACTION:
        {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            String callingPackage = data.readString();
            Intent intent = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            IBinder resultTo = data.readStrongBinder();
            String resultWho = data.readString();
            int requestCode = data.readInt();
            int startFlags = data.readInt(); // 读取数据
            ProfilerInfo profilerInfo = data.readInt() != 0
                    ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
            Bundle options = data.readInt() != 0
                    ? Bundle.CREATOR.createFromParcel(data) : null;
            int result = startActivity(app, callingPackage, intent, resolvedType,
                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
            reply.writeNoException();
            reply.writeInt(result);
            return true;
        }
•••
}

这些流程都运行与AMS所在的进程,需要注意的是ActivityManagerService服务继承于ActivityManagerNative,

 onTransact方法是运行于服务进程中,并且startActivity方法是调用子类ActivityManagerService中的startActivity方法。

这样就完成第一次跨进程通信。详细的binder机制在此就不论述了。

AMS的startActivity方法如下,

public final int startActivity(IApplicationThread caller, String callingPackage,
 Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
 int startFlags, ProfilerInfo profilerInfo, Bundle options) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, options,
            UserHandle.getCallingUserId());
    }

直接调用了startActivityAsUser方法,

public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
   Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
    enforceNotIsolatedCaller("startActivity");
    userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, false, userId, null, null);
    }

StackSupervisorstartActivityMayWait方法如下,

final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
            Bundle options, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
            •••

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

startActivityMayWait比较长,但是逻辑简单,首先调用resolveActivity方法获取需要启动的Activity信息,resolveActivity方法调用PMS

的resolveIntent方法具体匹配要启动的activity信息。得到activity后,继续调用startActivityLocked方法启动。

startActivityLocked方法检查各种错误,检查调用者的权限以及intent防火墙等等。

ActivityStackSupervisor类从名字就可知道,它管理各种包含activity的栈。

private ActivityStack mHomeStack;  // 系统的第一个栈对象
private ActivityStack mFocusedStack; // 系统前台栈对象
•••

startActivityUncheckedLocked方法也比较长,主要就是判断intent标志和activity属性来确定activity的栈。确定栈之后

就调用其startActivityLocked方法

startActivityLocked方法就是将ActivityRecord对象加入到栈的顶部,同时把该栈放到mHistoryStack的顶部。这里也调

用了WMS方法来处理Activity的显示和切换。

步骤12,13,14就是在ActivityStackSupervisor 和ActivityStack中倒过来到过去而已,就是准备启动activity。直接看

resumeTopActivityInnerLocked方法

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
        next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                        mService.isNextTransitionForward(), resumeAnimOptions);

        mStackSupervisor.startSpecificActivityLocked(next, true, false);
•••
}

这里分2种情况,

1,目标acitivity已经启动,就直接跨进程调用scheduleResumeActivity方法

2,如果acitivity未启动,调用startSpecificActivityLocked方法。

1,scheduleResumeActivity

scheduleResumeActivity方法是通过跨进程通信,从AMS进程到目标activity所在的进程。最后调用目标activity的onResume方法。

2,startSpecificActivityLocked

在startSpecificActivityLocked方法中,又分为2种情况,

如果目标activity所在进程已经启动,则直接调用realStartActivityLocked启动目标activity,调用其oncreate方法;否则,首先启动目标

activity所在进程,然后启动目标activity。

3, 客户端(目标进程)

客户端调用流程图如下,

AMS跨进程一般调用schedule····方法,到ActivityThread的内部类ApplicationThread中,此时代码还运行于Binder线程池中,

然后通过向主线程类(ActivityThread的内部类H)发送消息,跳到目标进程的主线程中执行,最后分别调目标Activity的onResume, oncreate 方法。

 

小结:

ActivityManagerServices,简称AMS,服务端对象,负责系统中所有Activity的生命周期。

ActivityThread,App的真正入口。当开启App之后,会调用main()开始运行,开启消息循环队列,这就是传说中的UI线程

或者叫主线程。与ActivityManagerServices配合,一起完成Activity的管理工作。

ActivityManagerServices和 客户端的通信(主要是管理Activity等)

ApplicationThread,用来实现ActivityManagerService与ActivityThread之间的交互。在ActivityManagerService需要管理

相关Application中的Activity的生命周期时,通过ApplicationThread的代理对象与ActivityThread通讯。

ApplicationThreadProxy,是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通讯。AMS就是

通过该代理与ActivityThread进行通信的。

 

客户端 和 ActivityManagerServices的通信(主要是发送相关请求)

ActivityManagerNative的代理类ActivityManagerProxy,其实就是AMS在客户端的代理,客户端通过ActivityManagerProxy 对AMS发送请求。

 

Instrumentation,每一个应用程序只有一个Instrumentation对象,每个Activity内都有一个对该对象的引用。Instrumentation

可以理解为应用进程的管家,ActivityThread要创建或暂停某个Activity时,都需要通过Instrumentation来进行具体的操作。

ActivityStack,Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。

ActivityRecord,ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。

其实就是服务器端的Activity对象的映像。

TaskRecord,AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用

TaskRecord确保Activity启动和退出的顺序。如果你清楚Activity的4种launchMode,那么对这个概念应该不陌生。

 

启动activity的流程如下,

1,客户端向服务端的AMS发送启动activity的请求。

2,服务端AMS处理该请求,获取目标activity的基本信息等。

3,启动目标activity的进程,然后启动目标activity。

 

这里涉及到2个跨进程通信:

1,从apk到AMS。ActivityManagerProxy是AMS的在客户端的代理。

2,从AMS到apk。ApplicationThreadProxy,是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通讯。

AMS就是通过该代理与ActivityThread进行通信的。ApplicationThread是ActivityThread的内部类。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Activity启动模式是Android应用程序中非常重要的概念,它决定了Activity的启动方式和生命周期的管理方式。在Android中,Activity启动模式主要有以下几种: 1. standard:标准模式。默认情况下,每次启动Activity时都会创建一个新实例,并放入任务栈中。如果该Activity已经存在任务栈中,则会将该Activity放到栈顶,并重新调用其onCreate()方法。 2. singleTop:栈顶复用模式。如果新启动的Activity已经存在任务栈的栈顶,则不会创建新实例,而是将已有的实例作为当前任务的Activity,并调用其onNewIntent()方法。如果新启动的Activity不在栈顶,则会创建新实例,并将其放到任务栈的栈顶。 3. singleTask:栈内复用模式。如果新启动的Activity已经存在任务栈中,则不会创建新实例,而是将已有的实例作为当前任务的Activity,并将其上面的Activity全部出栈,调用其onNewIntent()方法。如果新启动的Activity不存在任务栈中,则会创建新实例,并放到任务栈的栈顶。 4. singleInstance:单例模式。在一个新的任务栈中创建Activity,并且该任务栈中只有该Activity实例。如果该Activity已经存在于其他任务栈中,则会将该任务栈中的该Activity实例移动到新的任务栈中。 下面是Activity源码分析: 1. standard模式 在Activity源码中,标准模式是默认的启动模式。当我们使用startActivity()方法启动一个Activity时,会调用ActivityStackSupervisor类中的startActivityLocked()方法。在该方法中,会通过ActivityStack类的findTaskLocked()方法查找是否存在当前Activity所在的任务栈。如果存在,则会将当前Activity放到该任务栈的栈顶,并调用其onCreate()方法。如果不存在,则会创建一个新的任务栈,并将当前Activity放到该任务栈的栈顶。 2. singleTop模式 当我们在Manifest文件中设置Activity的启动模式为singleTop时,会在ActivityInfo中保存该信息。在ActivityStackSupervisor类的startActivityLocked()方法中,会通过ActivityStack类的findTaskLocked()方法查找是否存在当前Activity所在的任务栈,并判断当前Activity是否在栈顶。如果在栈顶,则会调用其onNewIntent()方法。如果不在栈顶,则会创建一个新的实例,并放到该任务栈的栈顶。 3. singleTask模式 当我们在Manifest文件中设置Activity的启动模式为singleTask时,会在ActivityInfo中保存该信息。在ActivityStackSupervisor类的startActivityLocked()方法中,会通过ActivityStack类的findTaskLocked()方法查找是否存在当前Activity所在的任务栈。如果存在,则会找到该任务栈中的栈顶Activity,并将其上面的所有Activity出栈。然后将当前Activity放到该任务栈的栈顶,并调用其onNewIntent()方法。如果不存在,则会创建一个新的任务栈,并将当前Activity放到该任务栈的栈顶。 4. singleInstance模式 当我们在Manifest文件中设置Activity的启动模式为singleInstance时,会在ActivityInfo中保存该信息。在ActivityStackSupervisor类的startActivityLocked()方法中,会创建一个新的任务栈,并将当前Activity放到该任务栈的栈顶。如果该Activity已经存在于其他任务栈中,则会将该任务栈中的该Activity实例移动到新的任务栈中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值