Activity Result API 使用与源码分析

最后

最后,强调几点:

  • 1. 一定要谨慎对待写在简历上的东西,一定要对简历上的东西非常熟悉。因为一般情况下,面试官都是会根据你的简历来问的; 能有一个上得了台面的项目也非常重要,这很可能是面试官会大量发问的地方,所以在面试之前好好回顾一下自己所做的项目;
  • 2. 和面试官聊基础知识比如设计模式的使用、多线程的使用等等,可以结合具体的项目场景或者是自己在平时是如何使用的;
  • 3. 注意自己开源的Github项目,面试官可能会挖你的Github项目提问;

我个人觉得面试也像是一场全新的征程,失败和胜利都是平常之事。所以,劝各位不要因为面试失败而灰心、丧失斗志。也不要因为面试通过而沾沾自喜,等待你的将是更美好的未来,继续加油!

以上面试专题的答小编案整理成面试文档了,文档里有答案详解,以及其他一些大厂面试题目。

面试答案

三面头条+四面阿里+五面腾讯拿offer分享面经总结,最终入职阿里

三面头条+四面阿里+五面腾讯拿offer分享面经总结,最终入职阿里

三面头条+四面阿里+五面腾讯拿offer分享面经总结,最终入职阿里

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

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

}

});

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

}

最后

笔者已经把面试题和答案整理成了面试专题文档

image

image

image

image

image

image

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

者已经把面试题和答案整理成了面试专题文档**

[外链图片转存中…(img-iJNg867m-1715805470271)]

[外链图片转存中…(img-wV4fpqoj-1715805470272)]

[外链图片转存中…(img-uJ7uzWST-1715805470272)]

[外链图片转存中…(img-2nkGyLfC-1715805470272)]

[外链图片转存中…(img-p4Xszmdo-1715805470273)]

[外链图片转存中…(img-QwtJ3dPP-1715805470273)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值