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,再到attach、onCreate。
好了,Activity的启动流程快速了解一下,启动过程中层层传递的参数中就有requestCode,因为后面会用到的。启动Activity过程中在系统服务侧建立了每个Activity对应的ActivityRecord,其中就存有requestCode、resultWho以及存储的数据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启动流程类似,可以快速的定位流程:就从TaskFragment的resumeTopActivity()方法开始。
判断如果传递了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)中,执行对应Activity的onResume相关流程:
这里面会同时执行executeCallbacks()和executeLifecycleState(),而这分别是前面设置的:ActivityResultItem、ResumeActivityItem。它们都继承自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);
}
其中,ActivityResultItem的execute()方法实现如下:
@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);
...
}
最终requestCode、resultCode连同data一并回调到onActivityResult(int requestCode, int resultCode, Intent data)。
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
}
至此,通过本篇彻底了解了onActivityResult传递的前因后果,离不开Activity的生命周期。可以说涉及Activity的回调,大都是在生命周期间隙寻找合适的“位置”插入回调。
UML流程图:
github/quibbler01/startActivityForResult