Activity.startActivity()分析:本地进程部分

本文详细阐述了Android系统中Activity启动的过程,包括Activity、AMS和BActivity内部的工作流程,以及WMS相关操作。重点分析了Activity启动的主要方法及其参数,深入理解Android应用启动机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要内容

基本分析过程是一个Activity,a调用startActivity()启动b Activity(),Android系统内部进行的一些工作过程,主要分为三个过程,a Activity中的操作, AMS中的操作,B Activity中的操作,当中会有WMS相关的操作,基本目的是比较全面的分析一个Activity启动的全过程。

第一个A  Activity中的工作

/framework/base/core/java/android/app/Activity.java
这个类中有许多的以startActivity开头的方法:
public void startActivityForResult(Intent intent, int requestCode),
public void startActivityForResult(Intent intent, int requestCode, Bundle options),

public void startActivity(Intent intent),
public void startActivity(Intent intent, Bundle options),

public void startActivities(Intent[] intents),
public void startActivities(Intent[] intents, Bundle options),

public boolean startActivityIfNeeded(Intent intent, int requestCode),
public boolean startActivityIfNeeded(Intent intent, int requestCode, Bundle options),

public void startActivityFromChild(Activity child, Intent intent,int requestCode) ,
public void startActivityFromChild(Activity child, Intent intent, int requestCode, Bundle options)  


参数少的方法都是直接调用参数多的方法,其中参数多的方法中的参数options为null.

2.1 startActivity(Intent intent, Bundle options)

这个方法应该是最常用的方法,他的第一个参数是启动目标Activity的意图对象,Intent对象实质是一个Parcelable对象,因为这个对象需要进行跨进程传递给AMS,以使AMS能够根据这个对象找到正确的目标Activity信息。第二个参数用于传递数据,因为也是跨进程的,所以Bundle本身是一个Parcelable对象。

这个方法的实现就是直接调用startActivityForResule()方法。
    public void startActivity(Intent intent, 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);
        }
    }

2.2 startActivityForResult(Intent intent, int requestCode, Bundle options)

这个方法多了一个int型的参数,这个参数其实是一个返回值,如果这个值大于0,则这个值会在此Activity退出时返回给调用他的Activity。当直接startActivity()时,这个值是-1,所以默认是不会返回的。
     public void startActivityForResult(Intent intent, int requestCode, 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());
            }
            if (requestCode >= 0) {
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                // activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }
这个方法根据mParent是否为空来进行分支处理。这个变量声明为Activity mParent,他也是一个Activity,这个变量在Activity本地创建时会被赋值,具体是在Activity在attach的时候会被赋值。
final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config) {
        attachBaseContext(context);

        mFragments.attachActivity(this);
        
        mWindow = PolicyManager.makeNewWindow(this);<span style="white-space:pre">		</span>//这里申请一个surface
        mWindow.setCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        ...
        mParent = parent;
        ...
    }
这个方法attach()是在ActivityThread-->handleLaunchActivity-->performLaunchActivity中调用的,调用activity.attach(..., r.parent,...);这个r为一个ActivityClientRecord对象,是一个ActivityRecord的本地对象。mParent赋值具体原则是如果新建的Activity是ActivityTask的根Activity,则mParent为null,否则为ActivityTask的根Activity
如果mParent不为空,则调用startActivityFromChild()方法,否则调用mInstrumentation.execStartActivity(...);方法;而startActivityFromChild(..)方法的实现也是调用了mInstrumentation.execStartActivity(...)方法
    public void startActivityFromChild(Activity child, Intent intent, 
            int requestCode, Bundle options) {
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, child,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, child.mEmbeddedID, requestCode,
                ar.getResultCode(), ar.getResultData());
        }
    }
 即startActivity方法最终都会调用mInstrumentation.execStartActivity(...)方法,最终调用AMS启动新的Activity的操作也是在这个方法中执行的。

2.3 Instrumentation.java

/framework/base/core/java/android/app/Activity.java
/**
 * Base class for implementing application instrumentation code.  When running
 * with instrumentation turned on, this class will be instantiated for you
 * before any of the application code, allowing you to monitor all of the
 * interaction the system has with the application.  An Instrumentation
 * implementation is described to the system through an AndroidManifest.xml's
 * <instrumentation> tag.
 */
public class Instrumentation
这个类的对象会在Application之前创建对象,用于监督系统和Application直接的交互。
     public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        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, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }
        return null;
    }
可以知道他调用的是ActivityManagerNative里的startActivity方法。ActivityManagerNative是ActivityManagerService的本地代理类,由他代理和AMS之间的跨进程交互。这个类里面有很多的callActivityOnXx的方法,对应Activity的OnCreate等方法,即Activity的生命周期方法是在这个类里面调用的。ActivityManagerNative.startActivity方法会将调用者的进程信息,目标Activity的信息传递给AMS,一遍AMS去真正启动一个Activity组件。

2.4 ActivityManagerNative

/framework/base/core/java/android/app/ActivityManagerNative.java
      public int startActivity(IApplicationThread caller, 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);
        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);
        }
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }
方法一开始获取两个Parcel对象,data和reply,分别用于往AMS写数据,和从AMS获取结果。
然后开始往data中写入相关数据:
data.writeStrongBinder(caller != null ? caller.asBinder() : null);写入调用者进程信息。
intent.writeToParcel(data, 0);写入Intent信息
最重要的语句:mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);这段代码将开启AMS远程服务,注意这里传递的flag是
START_ACTIVITY_TRANSACTION<span style="font-family: Arial, Helvetica, sans-serif;">。mRemote对象是一个Binder的客户端,由ServiceManager返回,具体代码为:</span>
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
可见mRemote是通过ServiceManager获取的系统服务。transact方法里面会进行跨进程调用,具体使用Binder机制如何通信这里先不说,这一步的最后会调用ActivityManagerService里面的onTransact方法,而这个方法的具体实现也是在ActivityManagerNative里面,就是说在客户端和服务器端都有一个此类的对象。
/framework/base/core/java/android/app/ActivityManagerNative.java
这个方法有1500多行,会处理所有四大组件的相关事务,
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);
            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();
            String profileFile = data.readString();
            ParcelFileDescriptor profileFd = data.readInt() != 0
                    ? data.readFileDescriptor() : null;
            Bundle options = data.readInt() != 0
                    ? Bundle.CREATOR.createFromParcel(data) : null;
            int result = startActivity(app, intent, resolvedType,
                    resultTo, resultWho, requestCode, startFlags,
                    profileFile, profileFd, options);
            reply.writeNoException();
            reply.writeInt(result);
            return true;
        }
<span style="white-space:pre">	</span>...
<span style="white-space:pre">	</span>}
这个方法首先从data中取出数据,然后执行Activity启动过程中最重要的方法startActivity();



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值