写点什么

Activity Result API 使用与源码分析,移动端开发基础

用户头像
Android架构
关注
发布于: 18 小时前

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<String>


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<I> register(


@NonNull final String key,


@NonNull final LifecycleOwner lifecycleOwner,


@NonNull final ActivityResultContract<I, O> contract,


@NonNull final ActivityResultCallback<O> 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(parsedP


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


endingResult);


}


//从 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<I>() {


@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<O> 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

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Activity Result API 使用与源码分析,移动端开发基础