startActivityForResult的原理

Quibbler 2023-6-16 544

startActivityForResult的原理


        在startActivityForResult的用法一文中简单回顾了启动Activity之间传递数据的方法,这样的设计方便了开发者。背后的原理其实很简单,如果熟悉Activity启动流程,不难发现,其实startActivityForResult就穿插在其中。

        本篇探索startActivityForResult的原理,顺便回顾一下Activity启动流程



1、启动Activity:传递requestCode

        开发中,当我们调用startActivity,在应用侧执行的流程如下。代码太占篇幅,就不贴了。

        通过AIDL跨进程调用,进入到系统服务:这里即平时常说的AMS(亦或称之为ATMS),执行启动应用Activity的请求:

        系统server侧执行完对应的逻辑,将再次通过跨进程回调,回到应用所在的进程。从Android 11开始,和以往的方式不太一样。用类似“事务”的形式去执行Activity生命周期的流转,同时还夹带有各种业务的回调封装,比如本篇将要探索的ActivityResultItem


        接下来回到当前应用进程(ActivityThread/ApplicationThread)执行具体的启动Activity逻辑,比如这些开发中熟悉的回调方法:从handleLaunchActivity,到performLaunchActivity,再到attachonCreate


        好了,Activity的启动流程快速了解一下,启动过程中层层传递的参数中就有requestCode,因为后面会用到的。启动Activity过程中在系统服务侧建立了每个Activity对应的ActivityRecord,其中就存有requestCoderesultWho以及存储的数据results

    ActivityRecord resultTo; // who started this entry, so will get our reply
    final String resultWho; // additional identifier for use by resultTo.
    final int requestCode;  // code given by requester (resultTo)
    ArrayList<ResultInfo> results; // pending ActivityResult objs we have received

        Activity启动流程不是本篇的重点,另见Activity启动流程一文。



2、销毁Activity:准备result

        在startActivityForResult的用法一文中提到,setResult(int resultCode, Intent data)方法的调用要早于finish()方法的执行。

        当Activity的finish()执行时,会判断如果有调用setResult(int resultCode, Intent data)方法设置过resultData,就准备将其传递给上一个启动它的Activity。这里也是跨进程的,将resultCode以及将要传递的数据resultData设置到系统服务中对应的ActivityRecord(即上一个Activity:A)中。

    /**
     * Finishes the current activity and specifies whether to remove the task associated with this
     * activity.
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private void finish(int finishTask) {
        if (mParent == null) {
            int resultCode;
            Intent resultData;
            synchronized (this) {
                resultCode = mResultCode;
                resultData = mResultData;
            }
            if (false) Log.v(TAG, "Finishing self: token=" + mToken);
            if (resultData != null) {
                resultData.prepareToLeaveProcess(this);
            }
            if (ActivityClient.getInstance().finishActivity(mToken, resultCode, resultData,
                    finishTask)) {
                mFinished = true;
            }
        } else {
            mParent.finishFromChild(this);
        }
        getAutofillClientController().onActivityFinish(mIntent);
    }

        前面在第一节启动的过程中,我们了解到启动的时候传入的requestCode不为负,将会设置resultTo为上一个Activity对应的ActivityRecord,用来接收返回的数据。

    /**
     * Sets the result for activity that started this one, clears the references to activities
     * started for result from this one, and clears new intents.
     */
    private void finishActivityResults(int resultCode, Intent resultData,
            NeededUriGrants resultGrants) {
        // Send the result if needed
        if (resultTo != null) {
            ...
            resultTo.addResultLocked(this, resultWho, requestCode, resultCode, resultData);
            resultTo = null;
        ...
    }

        上面提到的ActivityRecord中的这些成员变量,将在返回上一个Activity时用到。



3、回调onActivityResult

        和Activity启动流程类似,可以快速的定位流程:就从TaskFragmentresumeTopActivity()方法开始。


        判断如果传递了resultData,即不为空,那么添加一个ActivityResultItem类型的callback

    final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
        ActivityRecord next = topRunningActivity(true /* focusableOnly */);
        if (next == null || !next.canResumeByCompat()) {
            return false;
        }
                ...
                ArrayList<ResultInfo> a = next.results;
                if (a != null) {
                    final int size = a.size();
                    if (!next.finishing && size > 0) {
                        if (DEBUG_RESULTS) {
                            Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a);
                        }
			//有数据,设置onResult回调
                        transaction.addCallback(ActivityResultItem.obtain(a));
                    }
                }
                if (next.newIntents != null) {
		    //注意这里有onNewIntent回调
                    transaction.addCallback(
                            NewIntentItem.obtain(next.newIntents, true /* resume */));
                }
                ...
		//设置生命周期onResume回调
                transaction.setLifecycleStateRequest(
                        ResumeActivityItem.obtain(next.app.getReportedProcState(),
                                dc.isNextTransitionForward()));
                mAtmService.getLifecycleManager().scheduleTransaction(transaction);
                ...
        return true;
    }

        随后设置ResumeActivityItem的生命周期回调,再跨进程回到应用进程执行:


        回到应用进程(ActivityThread/ApplicationThread)中,执行对应ActivityonResume相关流程:


        这里面会同时执行executeCallbacks()executeLifecycleState(),而这分别是前面设置的:ActivityResultItemResumeActivityItem。它们都继承自ClientTransaction

    /**
     * Resolve transaction.
     * First all callbacks will be executed in the order they appear in the list. If a callback
     * requires a certain pre- or post-execution state, the client will be transitioned accordingly.
     * Then the client will cycle to the final lifecycle state if provided. Otherwise, it will
     * either remain in the initial state, or last state needed by a callback.
     */
    public void execute(ClientTransaction transaction) {
        ...
        executeCallbacks(transaction);
        executeLifecycleState(transaction);
    }

        其中,ActivityResultItemexecute()方法实现如下:

    @Override
    public void execute(ClientTransactionHandler client, ActivityClientRecord r,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult");
        client.handleSendResult(r, mResultInfoList, "ACTIVITY_RESULT");
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

        其实ActivityThread继承自ClientTransactionHandler,并且实现了handleSendResult抽象方法:

    @Override
    public void handleSendResult(ActivityClientRecord r, List<ResultInfo> results, String reason) {
        ...
	//传递结果
        deliverResults(r, results, reason);
        if (resumed) {
            r.activity.performResume(false, reason);
        }
    }

        接着通过deliverResults传递消息到具体的Activity中:

    private void deliverResults(ActivityClientRecord r, List<ResultInfo> results, String reason) {
        final int N = results.size();
        for (int i=0; i<N; i++) {
            ResultInfo ri = results.get(i);
            ...
                r.activity.dispatchActivityResult(ri.mResultWho,
                        ri.mRequestCode, ri.mResultCode, ri.mData, reason);
            ...
        }
    }

        在Activity中,通过dispatchActivityResult方法分发全部数据(如果有1个或多个):

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    void dispatchActivityResult(String who, int requestCode, int resultCode, Intent data,
            String reason) {
        ...
            onActivityResult(requestCode, resultCode, data);
        ...
    }

        最终requestCoderesultCode连同data一并回调到onActivityResult(int requestCode, int resultCode, Intent data)

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    }



        至此,通过本篇彻底了解了onActivityResult传递的前因后果,离不开Activity的生命周期。可以说涉及Activity的回调,大都是在生命周期间隙寻找合适的“位置”插入回调。



UML流程图:

        github/quibbler01/startActivityForResult

        

不忘初心的阿甘
最新回复 (0)
    • 安卓笔记本
      2
        登录 注册 QQ
返回
仅供学习交流,切勿用于商业用途。如有错误欢迎指出:fluent0418@gmail.com