Jetpack撰写:从Composable函数启动ActivityResultContract请求 [英] Jetpack Compose: Launch ActivityResultContract request from Composable function

查看:158
本文介绍了Jetpack撰写:从Composable函数启动ActivityResultContract请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

截至 1.2.0-beta01 androidx.activity:activity-ktx ,不再可以启动使用 Activity.registerForActivityResult()创建的请求,如上面突出显示的那样在行为更改"下的链接并在此处的Google问题中看到.

As of 1.2.0-beta01 of androidx.activity:activity-ktx, one can no longer launch the request created using Activity.registerForActivityResult(), as highlighted in the above link under "Behavior Changes" and seen in the Google issue here.

应用程序现在应该如何通过 @Composable 函数启动此请求?以前,应用程序可以使用 Ambient MainActivity 的实例沿链向下传递,然后轻松启动请求.

How should an application launch this request via a @Composable function now? Previously, an app could pass the instance of the MainActivity down the chain via using an Ambient and then launch the request easily.

可以通过以下方法来解决新行为:例如,在Activity的 onCreate 函数之外实例化实例之后,在链中向下传递注册活动结果的类,然后在请求中启动请求. Composable .但是,无法以这种方式注册要在完成后执行的回调.

The new behavior can be worked around by, for example, passing a class registering for the activity result down the chain after being instantiated outside of the Activity's onCreate function, and then launch the request in a Composable. However, registering the a callback to be executed after completion cannot be done this way.

可以通过创建自定义的 ActivityResultContract 来解决此问题,该代码在启动时会进行回调.但是,这实际上意味着内置的 ActivityResultContracts 都不能与Jetpack Compose一起使用.

One could get around this by creating custom ActivityResultContract, which, at launch, take a callback. However, this would mean that virtually none of the built-in ActivityResultContracts could be used with Jetpack Compose.

TL; DR

应用程序如何通过 @Composable 函数启动 ActivityResultsContract 请求?

How would an app launch an ActivityResultsContract request from a @Composable function?

推荐答案

对于那些在我的案例中未使用@ianhanniballake提供的要领取回结果的人, returnedLauncher 实际上捕获了一个已经处置过的东西 realLauncher 的值.

For those who are not getting back a result with the gist provided by @ianhanniballake in my case the returnedLauncher actually captures an already disposed value of the realLauncher.

因此,尽管删除间接层应该可以解决此问题,但这绝对不是实现此目的的最佳方法.

So while removing the layer of indirection should fix the issue, it's definitely not the optimal way of doing this.

这是更新的版本,直到找到更好的解决方案为止:

Here's the updated version, until a better solution is found:

@Composable
fun <I, O> registerForActivityResult(
    contract: ActivityResultContract<I, O>,
    onResult: (O) -> Unit
): ActivityResultLauncher<I> {
    // First, find the ActivityResultRegistry by casting the Context
    // (which is actually a ComponentActivity) to ActivityResultRegistryOwner
    val owner = AmbientContext.current as ActivityResultRegistryOwner
    val activityResultRegistry = owner.activityResultRegistry

    // Keep track of the current onResult listener
    val currentOnResult = rememberUpdatedState(onResult)

    // It doesn't really matter what the key is, just that it is unique
    // and consistent across configuration changes
    val key = rememberSavedInstanceState { UUID.randomUUID().toString() }

    // TODO a working layer of indirection would be great
    val realLauncher = remember<ActivityResultLauncher<I>> {
        activityResultRegistry.register(key, contract) {
            currentOnResult.value(it)
        }
    }

    onDispose {
        realLauncher.unregister()
    }
    
    return realLauncher
}

这篇关于Jetpack撰写:从Composable函数启动ActivityResultContract请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆