override fun onCreate(owner: LifecycleOwner) {
getContent = registry.register(“key”, owner, ActivityResultContracts.GetContent(),
ActivityResultCallback { log(it) })
}
fun selectImage(){
getContent.launch(“image/*”)
}
}
使用版本activity-ktx:1.2.2,fragment-ktx:1.3.3
1.register
registerForActivityResult
方法最终会调用ActivityResultRegistry
的 register
方法,通过不同的key生成一个唯一的requestCode
,把这个requestCode
保存下来,在结果返回时使用。通过Lifecycle
添加一个观察者,监听Activity的ON_START,ON_STOP,ON_DESTROY
事件。在ON_START
事件到来时,会从mPendingResults
这个bundle
对象中通过key获取结果,如果有结果,则将结果回调到调用者处。ON_STOP
事件则是移除这个key对应的CallbackAndContract
对象,ON_DESTROY
事件移除这个key对应的所有信息。最后返回ActivityResultLauncher
对象给调用者使用。
public final <I, O> ActivityResultLauncher register(
@NonNull final String key,
@NonNull final LifecycleOwner lifecycleOwner,
@NonNull final ActivityResultContract<I, O> contract,
@NonNull final ActivityResultCallback callback) {
Lifecycle lifecycle = lifecycleOwner.getLifecycle();
//每个请求的key也不一样,根据key生成一个唯一的requestCode
final int requestCode = registerKey(key);
//把lifecycle和observer统一封装到LifecycleContainer中
LifecycleContainer lifecycleContainer = mKeyToLifecycleContainers.get(key);
if (lifecycleContainer == null) {
lifecycleContainer = new LifecycleContainer(lifecycle);
}
LifecycleEventObserver observer = new LifecycleEventObserver() {
@Override
public void onStateChanged(
@NonNull LifecycleOwner lifecycleOwner,
@NonNull Lifecycle.Event event) {
if (Lifecycle.Event.ON_START.equals(event)) {//处理回调
mKeyToCallback.put(key, new CallbackAndContract<>(callback, contract));
if (mParsedPendingResults.containsKey(key)) {
@SuppressWarnings(“unchecked”)
final O parsedPendingResult = (O) mParsedPendingResults.get(key);
mParsedPendingResults.remove(key);
callback.onActivityResult(parsedPendingResult);
}
//从bundle中获取结果
final ActivityResult pendingResult = mPendingResults.getParcelable(key);
if (pendingResult != null) {
mPendingResults.remove(key);
//把结果回调给调用者
callback.onActivityResult(contract.parseResult(
pendingResult.getResultCode(),
pendingResult.getData()));
}
} else if (Lifecycle.Event.ON_STOP.equals(event)) {
mKeyToCallback.remove(key);//stop时移除
} else if (Lifecycle.Event.ON_DESTROY.equals(event)) {
unregister(key);//destory时注销
}
}
};
//添加观察者
lifecycleContainer.addObserver(observer);
mKeyToLifecycleContainers.put(key, lifecycleContainer);
//返回ActivityResultLauncher对象
return new ActivityResultLauncher() {
@Override
public void launch(I input, @Nullable ActivityOptionsCompat options) {
mLaunchedKeys.add(key);
//ActivityResultRegistry的onLaunch,抽象方法,在ComponentActivity内实现
onLaunch(requestCode, contract, input, options);
}
public void unregister() {
ActivityResultRegistry.this.unregister(key);
}
public ActivityResultContract<I, ?> getContract() {
return contract;
}
};
}
2.launch
ActivityResultRegistry
的onLaunch
是一个抽象方法,在ComponentActivity
内实现。首先会检查contract
是否能获取同步结果,如果能,则直接分发处理。比如权限申请,我前面已经获取了权限,直接可以通过getSynchronousResult
查询是否有权限。有直接返回true
,不再通过requestPermissions
去做申请权限。
在通过contract
获取Intent
,按Intent分为三种情况处理,第一种,权限申请,通过requestPermissions
去申请权限,第二种处理INTENT_SENDER
,和startIntentSenderForResult
类似。第三种,处理其它问题,通过startActivityForResult
启动Activity
public <I, O> void onLaunch(
final int requestCode,
@NonNull ActivityResultContract<I, O> contract,
I input,
@Nullable ActivityOptionsCompat options) {
ComponentActivity activity = ComponentActivity.this;
//如果能直接拿到结果,直接分发处理了。
final ActivityResultContract.SynchronousResult synchronousResult =
contract.getSynchronousResult(activity, input);
if (synchronousResult != null) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
dispatchResult(requestCode, synchronousResult.getValue());
}
});
return;
}
// 根据协定创建Intent对象
Intent intent = contract.createIntent(activity, input);
Bundle optionsBundle = null;
// If there are any extras, we should defensively set the classLoader
if (intent.getExtras() != null && intent.getExtras().getClassLoader() == null) {
intent.setExtrasClassLoader(activity.getClassLoader());
}
if (intent.hasExtra(EXTRA_ACTIVITY_OPTIONS_BUNDLE)) {
optionsBundle = intent.getBundleExtra(EXTRA_ACTIVITY_OPTIONS_BUNDLE);
intent.removeExtra(EXTRA_ACTIVITY_OPTIONS_BUNDLE);
} else if (options != null) {
optionsBundle = options.toBundle();
}
//处理权限
if (ACTION_REQUEST_PERMISSIONS.equals(intent.getAction())) {
// requestPermissions path
String[] permissions = intent.getStringArrayExtra(EXTRA_PERMISSIONS);
if (permissions == null) {
permissions = new String[0];
}
ActivityCompat.requestPermissions(activity, permissions, requestCode);
} else if (ACTION_INTENT_SENDER_REQUEST.equals(intent.getAction())) {
//处理StartIntentSenderForResult
IntentSenderRequest request =
intent.getParcelableExtra(EXTRA_INTENT_SENDER_REQUEST);
try {
// startIntentSenderForResult path
ActivityCompat.startIntentSenderForResult(activity, request.getIntentSender(),
requestCode, request.getFillInIntent(), request.getFlagsMask(),
request.getFlagsValues(), 0, optionsBundle);
} catch (final IntentSender.SendIntentException e) {
}
} else {
//其它普通问题启动Activity
ActivityCompat.startActivityForResult(activity, intent, requestCode, optionsBundle);
}
}
3.结果回调
在ComponentActivity
中,onActivityResult和onRequestPermissionsResult
方法会先被ActivityResultRegistry的dispatchResult
方法拦截,如果它能处理,则不再调用Activity的方法。
dispatchResult
会调用doDispatch
来处理结果,这有两种情况,通过key
从mKeyToCallback
中获取callbackAndContract
对象,如果不为空,则直接回调结果。比如权限申请,不会走ON_STOP
事件,mKeyToCallback
不会被清除,这里就不会为空。如果为空则把结果放到mPendingResults
这个Bundle
对象中,和前面的ON_START
事件对应起来,从mPendingResults
取出结果,回调结果。
-ComponentActivity.java
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (!mActivityResultRegistry.dispatchResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
public void onRequestPermissionsResult(
int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults) {
if (!mActivityResultRegistry.dispatchResult(requestCode, Activity.RESULT_OK, new Intent()
.putExtra(EXTRA_PERMISSIONS, permissions)
.putExtra(EXTRA_PERMISSION_GRANT_RESULTS, grantResults))) {
if (Build.VERSION.SDK_INT >= 23) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
- ActivityResultRegistry.java
public final boolean dispatchResult(int requestCode, int resultCode, @Nullable Intent data) {
String key = mRcToKey.get(requestCode);
if (key == null) {
return false;
}
mLaunchedKeys.remove(key);
doDispatch(key, resultCode, data, mKeyToCallback.get(key));
return true;
}
private void doDispatch(String key, int resultCode, @Nullable Intent data,
@Nullable CallbackAndContract callbackAndContract) {
callbackAndContract不为空则直接回调即可
if (callbackAndContract != null && callbackAndContract.mCallback != null) {
ActivityResultCallback callback = callbackAndContract.mCallback;
ActivityResultContract<?, O> contract = callbackAndContract.mContract;
callback.onActivityResult(contract.parseResult(resultCode, data));
} else {把结果放到mPendingResults中。等会调用。
// Remove any parsed pending result
mParsedPendingResults.remove(key);
// And add these pending results in their place
mPendingResults.putParcelable(key, new ActivityResult(resultCode, data));
}
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
【附】相关架构及资料
源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,和技术大牛一起讨论交流解决问题。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
[外链图片转存中…(img-izoUhrUo-1713705774405)]
【附】相关架构及资料
源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,和技术大牛一起讨论交流解决问题。
[外链图片转存中…(img-a1CqTiyy-1713705774406)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!