Activity Result API 使用与源码分析(2)

文章介绍了如何通过实现LifecycleObserver在Android中接收Activity的结果,包括`registerForActivityResult`方法的使用,以及在onCreate阶段注册协定,展示了如何在不同生命周期事件中处理返回的结果。
摘要由CSDN通过智能技术生成
6.在其它类中接收Activity的结果

需要通过实现LifecycleObserver来实现协定的注册和启动器启动。

Activity注册这个观察者

var myLifecycleObserver=MyLifecycleObserver(registry = activityResultRegistry)

lifecycle.addObserver(myLifecycleObserver)

调用

myLifecycleObserver.selectImage()

实现DefaultLifecycleObserver,在onCreate注册协定

class MyLifecycleObserver(private val registry : ActivityResultRegistry) :DefaultLifecycleObserver{

lateinit var getContent : ActivityResultLauncher

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方法最终会调用ActivityResultRegistryregister方法,通过不同的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

ActivityResultRegistryonLaunch是一个抽象方法,在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来处理结果,这有两种情况,通过keymKeyToCallback中获取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;

}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

总结

最后小编想说:不论以后选择什么方向发展,目前重要的是把Android方面的技术学好,毕竟其实对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

这里附上我整理的几十套腾讯、字节跳动,京东,小米,头条、阿里、美团等公司19年的Android面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

技术进阶之路很漫长,一起共勉吧~

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

这里附上我整理的几十套腾讯、字节跳动,京东,小米,头条、阿里、美团等公司19年的Android面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

[外链图片转存中…(img-cUmw5k6n-1713705808587)]

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

技术进阶之路很漫长,一起共勉吧~

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值