Jetpack撰写:从Composable函数启动ActivityResultContract请求 [英] Jetpack Compose: Launch ActivityResultContract request from Composable function
问题描述
截至 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屋!