activity详解(二 源码篇)

想要剖析一个activity灵魂深处的秘密,必然要从“召唤”它的地方开始,一步一步跟踪到它结束,那么现在让我们在源码内一步一步了解他的整个生命周期吧

一般来说,我们打开一个activity的方式是使用startActivity方法来打开一个Activity类的子类,所以查看第一个方法

    /**
     * Same as {@link #startActivity(Intent, Bundle)} with no options
     * specified.
     * 和startActivity(Intent, Bundle)方法相同,只不过没有定义Bundle
     *
     * @param intent The intent to start.
     *
     * @throws android.content.ActivityNotFoundException
     *
     * @see {@link #startActivity(Intent, Bundle)}
     * @see #startActivityForResult
     */
    @Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

这里我们可以知道,其实在传入一个intent参数之后startActivity方法后,其实它的内部又会调用一个不同参的startActivity的重载方法,那么继续查看这个方法

    /**
     * Launch a new activity.  You will not receive any information about when
     * the activity exits.  This implementation overrides the base version,
     * providing information about
     * the activity performing the launch.  Because of this additional
     * information, the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag is not
     * required; if not specified, the new activity will be added to the
     * task of the caller.
     * 启动一个新的activity.而在该activity退出时,你将不会收到任何信息.
     * 它实现并重写了基础版本,提供activity准备启动时的信息,
     * 因为附加的启动flag没有被强制要求需要填写,如果没有设置的话,新的activity将会被加入到调用的task栈内.
     * (结合下文可知,启动flag,类似FLAG_ACTIVITY_NEW_TASK的,定义的是activity的启动方式,和activity的四种启动模式有关)
     *
     * <p>This method throws {@link android.content.ActivityNotFoundException}
     * if there was no Activity found to run the given Intent.
     *
     * @param intent The intent to start.
     * @param options Additional options for how the Activity should be started.
     * See {@link android.content.Context#startActivity(Intent, Bundle)
     * Context.startActivity(Intent, Bundle)} for more details.
     *
     * @throws android.content.ActivityNotFoundException
     *
     * @see {@link #startActivity(Intent)}
     * @see #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);
        }
    } 

可以看到因为使用startActivity(intent),我们一般调用的都会是startActivityForResult(intent, -1),那么startActivityForResult方法是什么呢

    /**
     * Same as calling {@link #startActivityForResult(Intent, int, Bundle)}
     * with no options.
     *
     * @param intent The intent to start.
     * @param requestCode If >= 0, this code will be returned in
     *                    onActivityResult() when the activity exits.
     * requestCode如果大于1,那么在activity结束后,会在onActivityResult()方法中返回这个code值
     * (默认传入的是-1,所以不会在activity结束后返回code值)
     *
     * @throws android.content.ActivityNotFoundException
     *
     * @see #startActivity
     */
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
    }

得,又是一个重载方法

    /**
     * Launch an activity for which you would like a result when it finished.
     * When this activity exits, your
     * onActivityResult() method will be called with the given requestCode.
     * Using a negative requestCode is the same as calling
     * {@link #startActivity} (the activity is not launched as a sub-activity).
     * 如果你想启动一个结束时带有结果返回值的activity,你需要调用onActivityResult() 方法及传入的requestCode值.
     * 使用负数作为requestCode的话将会和调用startActivity方法的结果一样(该activity并不会作为子activity启动,我的理解是结束时并不会有返回值)
     * 
     * <p>Note that this method should only be used with Intent protocols
     * that are defined to return a result.  In other protocols (such as
     * {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may
     * not get the result when you expect.  For example, if the activity you
     * are launching uses the singleTask launch mode, it will not run in your
     * task and thus you will immediately receive a cancel result.
     *
     * <p>As a special case, if you call startActivityForResult() with a requestCode
     * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your
     * activity, then your window will not be displayed until a result is
     * returned back from the started activity.  This is to avoid visible
     * flickering when redirecting to another activity.
     *
     * <p>This method throws {@link android.content.ActivityNotFoundException}
     * if there was no Activity found to run the given Intent.
     *
     * @param intent The intent to start.
     * @param requestCode If >= 0, this code will be returned in
     *                    onActivityResult() when the activity exits.
     * @param options Additional options for how the Activity should be started.
     * See {@link android.content.Context#startActivity(Intent, Bundle)
     * Context.startActivity(Intent, Bundle)} for more details.
     *
     * @throws android.content.ActivityNotFoundException
     *
     * @see #startActivity
     */
    public void startActivityForResult(@RequiresPermission 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());
            }
            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;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } 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是个啥,为什么这边要判断是否是null

如果往上翻,我们可以看到mParent是个Activity,并且有两个和他相关的方法

    /** Is this activity embedded inside of another activity? */
    //这个activity是不是内嵌在其他activity之内的
    public final boolean isChild() {
        return mParent != null;
    }

    /** Return the parent activity if this view is an embedded child. */
    //如果这个activity是被内嵌的子activity,返回其父activity
    public final Activity getParent() {
        return mParent;
    }

一般而言都不会被内嵌,所以我们看if内的代码即可

        //如果父activity为空
        if (mParent == null) {
            //可以看到想要继续分析acticity的启动过程,必须要从Instrumentation.ActivityResult入手了
            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());
            }
            //如果requestCode大于等于0,则是需要返回的code的,那么将mStartedActivity
            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;
            }
            //为子窗口考虑清理/刷新其他事件源及事件
            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.

那么继续追,往Instrumentation类深入,看看execStartActivity方法究竟是啥

    /**
     * Execute a startActivity call made by the application.  The default
     * implementation takes care of updating any active {@link ActivityMonitor}
     * objects and dispatches this call to the system activity manager; you can
     * override this to watch for the application to start an activity, and
     * modify what happens when it does.
     * 完成应用程序发起的startActivity方法的调用。默认实现负责更新任何活动对象并将此调用分派给系统activity管理器;
     * 你可以重写它然后观察应用启动activity的过程,然后看看它会发生什么
     *
     * <p>This method returns an {@link ActivityResult} object, which you can
     * use when intercepting application calls to avoid performing the start
     * activity action but still return the result the application is
     * expecting.  To do this, override this method to catch the call to start
     * activity so that it returns a new ActivityResult containing the results
     * you would like the application to see, and don't call up to the super
     * class.  Note that an application is only expecting a result if
     * <var>requestCode</var> is &gt;= 0.
     *
     * <p>This method throws {@link android.content.ActivityNotFoundException}
     * if there was no Activity found to run the given Intent.
     *
     * @param who The Context from which the activity is being started.
     * who 正在开启activity的activity的上下文对象context
     * @param contextThread The main thread of the Context from which the activity
     *                      is being started.
     * contextThread 正在开启activity的activity的上下文对象context的主线程
     * @param token Internal token identifying to the system who is starting
     *              the activity; may be null.
     * token 正在启动activity的系统的内部令牌标示;可能是null
     * @param target Which activity is performing the start (and thus receiving
     *               any result); may be null if this call is not being made
     *               from an activity.
     * target 哪个activity正在被执行启动(并且会接收任何结果);如果调用不是从另外一个activity发起的,它可能会是null
     * @param intent The actual Intent to start.
     * intent 开始的实际意图(其实没啥翻译的,intent就是intent,意图)
     * @param requestCode Identifier for this request's result; less than zero
     *                    if the caller is not expecting a result.
     * requestCode 为了请求的结果而定义;如果不期待结果,则该值定义小于零即可
     * @param options Addition options.
     * options 添加的操作
     *
     * @return To force the return of a particular result, return an
     *         ActivityResult object containing the desired data; otherwise
     *         return null.  The default implementation always returns null.
     * 强制返回一个特殊的结果,返回一个包含所需数据的ActivityResult对象;否则返回null。默认实现总是返回null。
     *
     * @throws android.content.ActivityNotFoundException
     *
     * @see Activity#startActivity(Intent)
     * @see Activity#startActivityForResult(Intent, int)
     * @see Activity#startActivityFromChild
     *
     * {@hide}
     */
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        //正在开启activity的activity的上下文对象context的主线程
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        //定义一个referrer(引荐?),其值为target是否为空,不为空则是target.onProvideReferrer(),为空则也为空
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        //如果referrer不为空,将其放入intent
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        //如果mActivityMonitors(activity监控器)不为空
        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()) {
                            //如果requestCode大于等于0,ActivityMonitor则会调用am.getResult()方法
                            //猜测返回结果即是用ActivityMonitor监控activity状态,然后获取结果,然后返回给父activity
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            //处理extra流
            intent.migrateExtraStreamToClipData();
            //做好intent的准备以离开程序进程
            intent.prepareToLeaveProcess(who);
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            //检查返回的result的code是哪种情况,以判断activity是否被成功开启
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

可以看到该try代码块中的ActivityManagerNative.getDefault().startActivity()方法才是开启activity的核心代码,继续深入观察它在干什么

来到ActivityManagerNative类

可以看到ActivityManagerNative.getDefault().startActivity()中的getDefault()是一个get方法,返回activity管理器(继续跟下去的话会发现getDefault()方法其实只是为了找到唯一的那个实例对象)

 

    /**
     * Retrieve the system's default/global activity manager.
     */
    static public IActivityManager getDefault() {
        return gDefault.get();
    }

 

重点其实在startActivity()方法中,startActivity()方法其实是ActivityManagerNative类中内嵌类ActivityManagerProxy的一个公有方法

    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是一种存放读取数据的容器,目测应该可以理解为一个封装好的数据类,它是轻量且高效的对象序列化和反序列化机制
        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);
        }
        //只研究activity的启动的话,不用太在意上面的代码,粗略一看,知道是往Parcel里面写数据即可
        //附带START_ACTIVITY_TRANSACTION的code及上面填好的data数据,执行transact()方法
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }

于是往transact()方法继续追,会发现transact()方法是ActivityManagerNative父类Binder的方法

    /**
     * Default implementation rewinds the parcels and calls onTransact.  On
     * the remote side, transact calls into the binder to do the IPC.
     * 默认实现会发回封装好的data数据(Parcel类)并且调用onTransact()方法。
     * 在远程方面,在Binder中处理调用已完成进程间通信(IPC)
     */
    public final boolean transact(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException {
        if (false) Log.v("Binder", "Transact: " + code + " to " + this);

        if (data != null) {
            data.setDataPosition(0);
        }
        //这里调用了onTransact()方法,并且将之前传入的code和data又发送出去
        boolean r = onTransact(code, data, reply, flags);
        if (reply != null) {
            reply.setDataPosition(0);
        }
        return r;
    }

那么onTransact()方法又在哪呢,Binder内有,但是其实具体的实现被其子类ActivityManagerNative重写了

于是又回到ActivityManagerNative类,由于该方法过长,我们只看其中的一部分,之前传入了一个code,即START_ACTIVITY_TRANSACTION,在ActivityManagerNative类中的onTransact()方法中有一个switch用于执行具体code的具体方法,所以我们研究START_ACTIVITY_TRANSACTION的这一段即可

 

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

        return super.onTransact(code, data, reply, flags);
    }

 

转载于:https://www.cnblogs.com/Qunter/p/7992930.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值