Activity Result API 使用与源码分析(1),海尔前端面试

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

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

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

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
img

正文

Activity Result API 提供了用于注册结果、启动结果以及在系统分派结果后对其进行处理的组件。 用来代替startActivityForResult()onActivityResult()。Google已经在新版的androidx activity和fragment中将这两个方法置为Deprecated,以后推荐使用的则是这套新的API官方文档-获取 activity 的结果

2.启动其它Activity并返回结果

使用registerForActivityResult方法注册一个启动项,第一个参数是内置的协定StartActivityForResult,用来启动Activity并返回结果。第二个参数是ActivityResultCallback,处理结果的回调,相当于以前onActivityResult方法。该方法返回结果是一个ActivityResultLauncher,在需要的地方调用它的launch方法即可。

var start=registerForActivityResult(ActivityResultContracts.StartActivityForResult()){

if(it.resultCode==Activity.RESULT_OK){

var result=it.data?.getStringExtra(“result”)

binding.tv.text=“result:${result}”

}

}

binding.btn.setOnClickListener {

val intent=Intent(this,MainActivity14::class.java).apply {

putExtra(“text”,“hello MainActivity14”)

}

start.launch(intent)

}

3.权限申请

它还可以用来做权限申请,使用RequestPermission协定,在launch方法中传入需要申请的权限,如果用户授权则会在回调中返回ture。还可以使用RequestMultiplePermissions来申请多个权限,相比以前的权限申请真的简单很多。

val requestPermission = registerForActivityResult(ActivityResultContracts.RequestPermission()) {

log(“permission:$it”)

}

binding.btn.setOnClickListener {

requestPermission.launch(android.Manifest.permission.ACCESS_FINE_LOCATION)

}

4.其它内置ActivityResultContract

ActivityResultContracts中内置了一些基本的协定。比如启动Activity,拍照返回结果,选联系人,请求权限等。用法类似,只是请求的参数和返回的结果不同。

5.自定义ActivityResultContract

如果系统内置协定不满足需求,可以通过继承ActivityResultContract类来自定义协定,ActivityResultContract有两个范型参数,InputOutput。然后现实它的两个方法,createIntent方法来创建你的意图IntentparseResult方法通过resultCodeintent来解析结果并返回Output类型。 类似StartActivityForResult源码

public static final class StartActivityForResult

extends ActivityResultContract<Intent, ActivityResult> {

public Intent createIntent(@NonNull Context context, @NonNull Intent input) {

return input;

}

public ActivityResult parseResult(

int resultCode, @Nullable Intent intent) {

return new ActivityResult(resultCode, intent);

}

}

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());

}

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

st(new Runnable() {

@Override

public void run() {

dispatchResult(requestCode, synchronousResult.getValue());

}

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-mj9piL0F-1713617196176)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 20
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值