Android Activity 结果回调处理模块深度剖析
本人掘金号,欢迎点击关注:掘金号地址
本人公众号,欢迎点击关注:公众号地址
一、引言
在 Android 开发中,Activity 作为四大组件之一,承担着用户界面展示和交互的重要职责。而 Activity 之间的通信与交互更是开发过程中的常见需求,其中 Activity 结果回调处理模块尤为关键。当一个 Activity 启动另一个 Activity 并期望获取其返回结果时,就需要借助 Activity 结果回调机制。本博客将从源码级别深入分析 Android 的 Activity 结果回调处理模块,为开发者提供全面而深入的理解。
二、Activity 结果回调基础概念
2.1 基本使用场景
在 Android 应用中,经常会遇到一个 Activity 需要启动另一个 Activity 并获取其操作结果的情况。例如,在一个图片选择器应用中,主 Activity 启动图片选择 Activity,用户在图片选择 Activity 中选择了一张图片后,需要将该图片的信息返回给主 Activity。这就需要使用 Activity 结果回调机制来实现。
2.2 传统使用方式示例
以下是一个简单的传统 Activity 结果回调使用示例:
java
java
// 主 Activity
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CODE = 1; // 请求码,用于区分不同的请求
private TextView resultTextView; // 用于显示结果的 TextView
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
resultTextView = findViewById(R.id.resultTextView); // 初始化 TextView
Button startActivityButton = findViewById(R.id.startActivityButton); // 初始化启动 Activity 的按钮
// 为按钮设置点击事件监听器
startActivityButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 创建启动目标 Activity 的 Intent
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
// 启动目标 Activity 并期望获取结果,传入请求码
startActivityForResult(intent, REQUEST_CODE);
}
});
}
// 处理返回结果的方法
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// 检查请求码是否匹配
if (requestCode == REQUEST_CODE) {
// 检查结果码是否为 RESULT_OK
if (resultCode == RESULT_OK) {
// 从返回的 Intent 中获取数据
String result = data.getStringExtra("result");
// 将结果显示在 TextView 上
resultTextView.setText("Result: " + result);
}
}
}
}
// 目标 Activity
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Button returnResultButton = findViewById(R.id.returnResultButton); // 初始化返回结果的按钮
// 为按钮设置点击事件监听器
returnResultButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 创建用于返回数据的 Intent
Intent resultIntent = new Intent();
// 向 Intent 中添加数据
resultIntent.putExtra("result", "This is the result");
// 设置结果码为 RESULT_OK
setResult(RESULT_OK, resultIntent);
// 关闭当前 Activity
finish();
}
});
}
}
2.3 代码解释
- 在
MainActivity
中,通过startActivityForResult
方法启动SecondActivity
并传入请求码REQUEST_CODE
。 SecondActivity
中,当用户点击returnResultButton
时,创建一个包含结果数据的Intent
,并通过setResult
方法设置结果码和返回的Intent
,最后调用finish
方法关闭当前 Activity。MainActivity
中的onActivityResult
方法会在SecondActivity
关闭后被调用,在该方法中检查请求码和结果码,并从返回的Intent
中获取结果数据。
三、Activity 结果回调处理模块源码分析
3.1 startActivityForResult 方法源码分析
在 Activity
类中,startActivityForResult
方法的源码如下:
java
java
/**
* 启动一个新的 Activity 并期望获取其返回结果
*
* @param intent 用于启动 Activity 的 Intent
* @param requestCode 请求码,用于区分不同的请求
*/
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
if (mParent == null) {
// 如果没有父 Activity,调用 Instrumentation 的 execStartActivity 方法
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, mOptions);
if (ar != null) {
// 如果有返回结果,调用 Activity 的 onActivityResult 方法
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
// 检查启动 Activity 是否有过渡动画
if (requestCode >= 0) {
// 如果有过渡动画,设置 Activity 过渡动画
mStartedActivity = true;
}
} else {
// 如果有父 Activity,调用父 Activity 的 startActivityForResult 方法
if (mOptions != null) {
mParent.startActivityFromChild(this, intent, requestCode, mOptions);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
3.1.1 代码解释
- 首先检查当前 Activity 是否有父 Activity,如果没有父 Activity,则调用
mInstrumentation.execStartActivity
方法来启动目标 Activity。 mInstrumentation.execStartActivity
方法会返回一个ActivityResult
对象,如果该对象不为空,则通过mMainThread.sendActivityResult
方法将结果发送给当前 Activity 的onActivityResult
方法进行处理。- 如果请求码大于等于 0,表示有过渡动画,设置
mStartedActivity
为true
。 - 如果有父 Activity,则调用父 Activity 的
startActivityFromChild
方法来启动目标 Activity。
3.2 Instrumentation.execStartActivity 方法源码分析
Instrumentation
类中的 execStartActivity
方法源码如下:
java
java
/**
* 执行启动 Activity 的操作
*
* @param who 启动 Activity 的上下文
* @param contextThread 应用程序的主线程
* @param token Activity 的令牌
* @param target 目标 Activity
* @param intent 用于启动 Activity 的 Intent
* @param requestCode 请求码
* @param options 启动 Activity 的选项
* @return Activity 结果
*/
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
// 如果有引用者,将引用者添加到 Intent 中
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
if (mActivityMonitors != null) {
// 如果有 Activity 监视器,检查是否匹配
synchronized (mActivityMonitors) {
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(who);
// 调用 ActivityManager 的 startActivityForResult 方法
int result = ActivityManager.getService()
.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;
}
3.2.2 代码解释
- 首先获取应用程序的主线程
whoThread
,并检查是否有引用者,如果有则将引用者添加到Intent
中。 - 检查是否有 Activity 监视器,如果有则遍历监视器列表,检查是否匹配当前的
Intent
,如果匹配则增加命中计数,若监视器为阻塞监视器,则返回模拟结果。 - 调用
ActivityManager.getService().startActivity
方法来启动目标 Activity,并传入请求码等参数。 - 调用
checkStartActivityResult
方法检查启动结果,如果出现异常则抛出RuntimeException
。 - 最后返回
null
,因为真正的结果会在后续处理中返回。
3.3 ActivityManager.startActivity 方法源码分析
ActivityManager
类中的 startActivity
方法是一个系统服务方法,其源码涉及到系统底层的实现,以下是简化后的调用流程:
java
java
// ActivityManagerService 中的 startActivity 方法(简化)
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
// ActivityManagerService 中的 startActivityAsUser 方法(简化)
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, ALLOW_FULL_ONLY, "startActivity", null);
// 调用 ActivityStarter 的 startActivityMayWait 方法
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null);
}
3.2.3 代码解释
startActivity
方法调用startActivityAsUser
方法,并传入当前用户的 ID。startActivityAsUser
方法会进行权限检查和用户 ID 处理,然后调用ActivityStarter
的startActivityMayWait
方法来启动目标 Activity。
3.4 ActivityStarter.startActivityMayWait 方法源码分析
ActivityStarter
类中的 startActivityMayWait
方法是启动 Activity 的核心方法,源码较长,以下是简化后的关键部分:
java
java
// ActivityStarter 中的 startActivityMayWait 方法(简化)
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 bOptions, boolean ignoreTargetSecurity, int userId,
TaskRecord inTask, ActivityRecord[] outActivity) {
// 解析 Intent
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
callingUid = callerApp.info.uid;
if (callingPackage == null) {
callingPackage = callerApp.info.packageName;
}
}
}
// 创建 ActivityRecord 对象
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, checkedOptions, sourceRecord);
// 调用 startActivityLocked 方法
return startActivityLocked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true, options, inTask, outActivity);
}
// ActivityStarter 中的 startActivityLocked 方法(简化)
private int startActivityLocked(ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, Bundle options, TaskRecord inTask,
ActivityRecord[] outActivity) {
// 检查启动权限
int err = ActivityManager.START_SUCCESS;
if (r.resultTo != null) {
// 如果有返回结果的目标,处理结果回调
ActivityRecord resultTo = r.resultTo;
if (resultTo.finishing) {
// 如果结果目标 Activity 正在结束,不处理结果
r.resultTo = null;
err = ActivityManager.START_NOT_ACTIVITY;
}
}
// 启动 Activity
mLastStartActivityResult = err;
mLastStartActivityRecord = r;
if (err == ActivityManager.START_SUCCESS) {
// 调用 resumeTopActivitiesLocked 方法启动 Activity
mSupervisor.resumeTopActivitiesLocked(null, r, options);
}
return err;
}
3.2.4 代码解释
startActivityMayWait
方法会解析Intent
,创建ActivityRecord
对象,该对象包含了 Activity 的相关信息,如请求码、结果目标等。startActivityLocked
方法会检查启动权限,如果有返回结果的目标,会处理结果回调。如果结果目标 Activity 正在结束,则不处理结果。- 最后调用
mSupervisor.resumeTopActivitiesLocked
方法来启动目标 Activity。
3.5 Activity 结果返回处理源码分析
当目标 Activity 调用 setResult
方法并调用 finish
方法关闭时,会触发结果返回处理。以下是 Activity
类中 setResult
方法的源码:
java
java
/**
* 设置 Activity 的返回结果
*
* @param resultCode 结果码
* @param data 用于返回的数据
*/
public final void setResult(int resultCode, Intent data) {
synchronized (this) {
// 设置结果码和返回数据
mResultCode = resultCode;
mResultData = data;
}
}
3.2.5 代码解释
setResult
方法会将结果码和返回的数据存储在Activity
的成员变量mResultCode
和mResultData
中。
当目标 Activity 调用 finish
方法时,会触发以下处理:
java
java
/**
* 关闭当前 Activity
*/
public void finish() {
finish(DONT_FINISH_TASK_WITH_ACTIVITY);
}
/**
* 关闭当前 Activity 并指定是否关闭任务
*
* @param finishTask 是否关闭任务
*/
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);
try {
if (resultData != null) {
resultData.prepareToLeaveProcess(this);
}
// 调用 ActivityManager 的 finishActivity 方法
if (ActivityManager.getService().finishActivity(mToken, resultCode, resultData, finishTask)) {
mFinished = true;
}
} catch (RemoteException e) {
// Empty
}
} else {
// 如果有父 Activity,调用父 Activity 的 finishFromChild 方法
mParent.finishFromChild(this);
}
}
3.2.6 代码解释
finish
方法会获取之前设置的结果码和返回数据,并调用ActivityManager.getService().finishActivity
方法将结果返回给启动该 Activity 的 Activity。- 如果有父 Activity,则调用父 Activity 的
finishFromChild
方法。
3.6 ActivityManager.finishActivity 方法源码分析
ActivityManager
类中的 finishActivity
方法源码如下:
java
java
// ActivityManagerService 中的 finishActivity 方法(简化)
@Override
public final boolean finishActivity(IBinder token, int resultCode, Intent resultData,
int finishTask) {
// 查找对应的 ActivityRecord
ActivityRecord r = ActivityRecord.isInStackLocked(token, mStackSupervisor);
if (r == null) {
return false;
}
// 处理结果回调
if (r.resultTo != null) {
ActivityRecord resultTo = r.resultTo;
if (resultTo.finishing) {
// 如果结果目标 Activity 正在结束,不处理结果
r.resultTo = null;
} else {
// 发送结果给结果目标 Activity
resultTo.deliverResultLocked(r, r.resultWho, r.requestCode, resultCode, resultData);
}
}
// 关闭 Activity
boolean res = mStackSupervisor.finishActivityLocked(r, resultCode, resultData, finishTask);
return res;
}
3.2.7 代码解释
- 首先根据传入的
token
查找对应的ActivityRecord
对象。 - 如果有结果目标 Activity 且该 Activity 没有正在结束,则调用
resultTo.deliverResultLocked
方法将结果发送给结果目标 Activity。 - 最后调用
mStackSupervisor.finishActivityLocked
方法关闭当前 Activity。
3.7 ActivityRecord.deliverResultLocked 方法源码分析
ActivityRecord
类中的 deliverResultLocked
方法源码如下:
java
java
// ActivityRecord 中的 deliverResultLocked 方法(简化)
void deliverResultLocked(ActivityRecord from, String resultWho, int requestCode,
int resultCode, Intent resultData) {
try {
// 创建 ActivityResult 对象
ActivityResult result = new ActivityResult(requestCode, resultCode, resultData);
// 调用 ActivityClientRecord 的 sendResult 方法
mApp.thread.scheduleSendResult(mToken, new ActivityResult[] { result });
} catch (RemoteException e) {
// Empty
}
}
3.2.8 代码解释
- 创建
ActivityResult
对象,包含请求码、结果码和返回数据。 - 调用
mApp.thread.scheduleSendResult
方法将结果发送给结果目标 Activity 的主线程。
3.8 ActivityThread.scheduleSendResult 方法源码分析
ActivityThread
类中的 scheduleSendResult
方法源码如下:
java
java
// ActivityThread 中的 scheduleSendResult 方法
@Override
public final void scheduleSendResult(IBinder token, ActivityResult[] results) {
// 创建 Message 对象
Message msg = Message.obtain();
msg.what = H.SEND_RESULT;
// 创建 ResultData 对象
ResultData data = new ResultData();
data.token = token;
data.results = results;
msg.obj = data;
// 发送消息到主线程的 Handler
mH.sendMessage(msg);
}
3.2.9 代码解释
- 创建
Message
对象,设置消息类型为H.SEND_RESULT
。 - 创建
ResultData
对象,包含Activity
的token
和ActivityResult
数组。 - 将
ResultData
对象设置为Message
的obj
,并发送消息到主线程的Handler
。
3.9 ActivityThread.H.handleMessage 方法中处理 SEND_RESULT 消息
在 ActivityThread
类的内部类 H
中,handleMessage
方法会处理 SEND_RESULT
消息,源码如下:
java
java
// ActivityThread.H 中的 handleMessage 方法(处理 SEND_RESULT 消息)
case SEND_RESULT: {
ResultData res = (ResultData) msg.obj;
// 查找对应的 ActivityClientRecord
ActivityClientRecord r = mActivities.get(res.token);
if (r != null) {
try {
// 调用 Activity 的 deliverResults 方法
r.activity.deliverResults(r, res.results);
} catch (Exception e) {
// Empty
}
}
break;
}
3.2.10 代码解释
- 从
Message
中获取ResultData
对象。 - 根据
ResultData
中的token
查找对应的ActivityClientRecord
对象。 - 如果找到对应的
ActivityClientRecord
,则调用Activity
的deliverResults
方法。
3.10 Activity.deliverResults 方法源码分析
Activity
类中的 deliverResults
方法源码如下:
java
java
// Activity 中的 deliverResults 方法
void deliverResults(ActivityClientRecord r, ActivityResult[] results) {
if (results != null) {
for (int i = 0; i < results.length; i++) {
// 调用 onActivityResult 方法处理结果
onActivityResult(results[i].mRequestCode, results[i].mResultCode, results[i].mData);
}
}
}
3.2.11 代码解释
- 遍历
ActivityResult
数组,调用onActivityResult
方法处理每个结果。
四、新的 Activity 结果 API(AndroidX Activity Result API)
4.1 引入背景
传统的 startActivityForResult
和 onActivityResult
方法在处理复杂场景时存在一些问题,例如代码逻辑分散、难以管理等。为了解决这些问题,AndroidX 引入了新的 Activity 结果 API。
4.2 基本使用示例
以下是一个使用新的 Activity 结果 API 的示例:
java
java
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private TextView resultTextView; // 用于显示结果的 TextView
private ActivityResultLauncher<Intent> activityResultLauncher; // Activity 结果启动器
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
resultTextView = findViewById(R.id.resultTextView); // 初始化 TextView
Button startActivityButton = findViewById(R.id.startActivityButton); // 初始化启动 Activity 的按钮
// 注册 Activity 结果启动器
activityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
// 处理返回结果
if (result.getResultCode() == RESULT_OK) {
Intent data = result.getData();
String resultText = data.getStringExtra("result");
resultTextView.setText("Result: " + resultText);
}
}
});
// 为按钮设置点击事件监听器
startActivityButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 创建启动目标 Activity 的 Intent
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
// 启动目标 Activity
activityResultLauncher.launch(intent);
}
});
}
}
// 目标 Activity 保持不变
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Button returnResultButton = findViewById(R.id.returnResultButton); // 初始化返回结果的按钮
// 为按钮设置点击事件监听器
returnResultButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 创建用于返回数据的 Intent
Intent resultIntent = new Intent();
// 向 Intent 中添加数据
resultIntent.putExtra("result", "This is the result");
// 设置结果码为 RESULT_OK
setResult(RESULT_OK, resultIntent);
// 关闭当前 Activity
finish();
}
});
}
}
4.3 代码解释
- 使用
registerForActivityResult
方法注册一个ActivityResultLauncher
,该方法接受一个ActivityResultContract
和一个ActivityResultCallback
。 ActivityResultContract
定义了启动 Activity 的方式和返回结果的类型,这里使用ActivityResultContracts.StartActivityForResult
表示启动一个 Activity 并获取结果。ActivityResultCallback
用于处理返回的结果,在onActivityResult
方法中处理结果。- 当需要启动目标 Activity 时,调用
ActivityResultLauncher
的launch
方法,并传入启动 Activity 的Intent
。
4.4 新 API 的源码分析
4.4.1 registerForActivityResult 方法源码分析
ComponentActivity
类中的 registerForActivityResult
方法源码如下:
java
java
// ComponentActivity 中的 registerForActivityResult 方法
public final <I, O> ActivityResultLauncher<I> registerForActivityResult(
@NonNull ActivityResultContract<I, O> contract,
@NonNull ActivityResultCallback<O> callback) {
return getActivityResultRegistry().register(
"activity_rq#" + nextLocalRequestCode(),
this,
contract,
callback);
}
4.4.1.1 代码解释
- 调用
getActivityResultRegistry().register
方法进行注册,传入一个唯一的请求码、当前 Activity、ActivityResultContract
和ActivityResultCallback
。
4.4.2 ActivityResultRegistry.register 方法源码分析
ActivityResultRegistry
类中的 register
方法源码如下:
java
java
// ActivityResultRegistry 中的 register 方法
public <I, O> ActivityResultLauncher<I> register(@NonNull final String key,
@NonNull final LifecycleOwner lifecycleOwner,
@NonNull final ActivityResultContract<I, O> contract,
@NonNull final ActivityResultCallback<O> callback) {
if (mParsedPendingResults.containsKey(key)) {
// 如果有未处理的结果,立即处理
final O parsedPendingResult = mParsedPendingResults.get(key);
mParsedPendingResults.remove(key);
callback.onActivityResult(parsedPendingResult);
}
// 创建 ActivityResultLauncher 对象
final ActivityResultLauncher<I> launcher = new ActivityResultLauncher<I>() {
@Override
public void launch(I input, @Nullable ActivityOptionsCompat options) {
// 启动 Activity
mKeyToCallback.put(key, callback);
mKeyToContract.put(key, contract);
mLaunchedKeys.add(key);
Intent intent = contract.createIntent(mContext, input);
if (options != null) {
ActivityCompat.startActivityForResult(
mContext,
intent,
mKeyToRc.get(key),
options.toBundle());
} else {
ActivityCompat.startActivityForResult(
mContext,
intent,
mKeyToRc.get(key),
null);
}
}
@Override
public void unregister() {
// 取消注册
mKeyToCallback.remove(key);
mKeyToContract.remove(key);
mLaunchedKeys.remove(key);
mKeyToRc.remove(key);
}
@NonNull
@Override
public ActivityResultContract<I, O> getContract() {
return contract;
}
};
// 注册生命周期观察者
lifecycleOwner.getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
// 在 Activity 销毁时取消注册
launcher.unregister();
}
}
});
return launcher;
}
4.4.2.1 代码解释
- 检查是否有未处理的结果,如果有则立即处理。
- 创建
ActivityResultLauncher
对象,该对象包含launch
、unregister
和getContract
方法。 launch
方法用于启动 Activity,将请求码、ActivityResultCallback
和ActivityResultContract
存储在相应的映射中,然后调用ActivityCompat.startActivityForResult
方法启动 Activity。unregister
方法用于取消注册,从映射中移除相应的信息。- 注册生命周期观察者,在 Activity 销毁时调用
unregister
方法取消注册。
4.4.3 ActivityResultRegistry.onActivityResult 方法源码分析
ActivityResultRegistry
类中的 onActivityResult
方法源码如下:
java
java
// ActivityResultRegistry 中的 onActivityResult 方法
public boolean onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
String key = mRcToKey.get(requestCode);
if (key == null) {
return false;
}
mLaunchedKeys.remove(key);
ActivityResultContract<?, ?> contract = mKeyToContract.get(key);
ActivityResultCallback<?> callback = mKeyToCallback.get(key);
if (contract != null && callback != null) {
// 解析结果
Object parsedResult = contract.parseResult(resultCode, data);
// 调用回调方法处理结果
callback.onActivityResult(parsedResult);
return true;
}
return false;
}
4.4.3.1 代码解释
- 根据请求码查找对应的
key
,如果key
不存在则返回false
。 - 从
mLaunchedKeys
中移除该key
,表示该请求已经处理。 - 获取对应的
ActivityResultContract
和ActivityResultCallback
。 - 调用
ActivityResultContract
的parseResult
方法解析结果。 - 调用
ActivityResultCallback
的onActivityResult
方法处理结果。
五、总结与展望
5.1 总结
通过对 Android 的 Activity 结果回调处理模块的源码分析,我们深入了解了传统的 startActivityForResult
和 onActivityResult
方法以及新的 AndroidX Activity Result API 的实现原理。
传统方法的实现涉及到 Activity
、Instrumentation
、ActivityManager
等多个类,通过一系列的调用和消息传递来完成 Activity 的启动和结果返回。这种方式在处理复杂场景时存在代码逻辑分散、难以管理的问题。
新的 AndroidX Activity Result API 通过 ActivityResultLauncher
和 ActivityResultRegistry
来管理 Activity 的启动和结果处理,将代码逻辑集中在一起,提高了代码的可读性和可维护性。同时,新 API 还支持生命周期管理,在 Activity 销毁时自动取消注册,避免了内存泄漏。
5.2 展望
随着 Android 开发的不断发展,Activity 结果回调处理模块可能会进一步优化和完善。未来可能会有更简洁、更强大的 API 出现,以满足开发者在不同场景下的需求。
同时,对于 Activity 结果回调处理模块的性能优化也是一个重要的研究方向。例如,减少不必要的消息传递和对象创建,提高启动 Activity 和处理结果的效率。
另外,在跨进程和跨应用的 Activity 结果回调处理方面,也有很大的发展空间。可以研究如何更安全、更高效地实现跨进程和跨应用的结果传递,为开发者提供更好的开发体验。
总之,Activity 结果回调处理模块是 Android 开发中不可或缺的一部分,深入理解其原理和不断探索其发展方向,对于提高 Android 应用的开发质量和效率具有重要意义。