如何使registerForActivityResult的参数可组合?

问题描述 投票:0回答:2

以下代码来自Android开发者文档。它解释了如何请求权限。

// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher. You can use either a val, as shown in this snippet,
// or a lateinit var in your onAttach() or onCreate() method.
val requestPermissionLauncher =
    registerForActivityResult(RequestPermission()
    ) { isGranted: Boolean ->
        if (isGranted) {
            // Permission is granted. Continue the action or workflow in your
            // app.
        } else {
            // Explain to the user that the feature is unavailable because the
            // features requires a permission that the user has denied. At the
            // same time, respect the user's decision. Don't link to system
            // settings in an effort to convince the user to change their
            // decision.
        }
    }

我尝试在我的应用程序中使用该代码。当

isGranted
为 true 时,我尝试渲染我的主用户界面。但它不起作用,因为我收到以下错误:

@Composable 调用只能在 @Composable 函数的上下文中发生

我想知道为什么会发生这种情况,因为我从可组合上下文中调用启动器。是否有必要将调用堆栈中的每个函数都标记为

@Composable
?如果是这样,如何使闭包传递给
registerForActivityResult
可组合?

android kotlin android-jetpack-compose android-permissions
2个回答
6
投票

您应该定义一个在结果返回后更新的状态。 记住的状态可以在有状态可组合项中或作为参数出现。 更新记住的状态将触发重组。

registerForActivity
中传入的Lambda是回调,在重组时会多次传递,但只会回调最后一次传递的。

你可以这样做:

@Composable
fun OnPermissionGranted(permission : String, launch : Boolean, onGranted : @Composable () -> Unit ){
    val context = LocalContext.current
    var granted by remember { mutableStateOf(checkIfGranted(context) ) }
    val launcher = rememberLauncherForActivityResult(contract = ActivityResultContracts.RequestPermission()){
        if(it){
            granted = true
        }
    }
    LaunchedEffect(granted, launch){
       if(!granted && launch){
          launcher.launch(permission)
       }
    }
    
    if(granted){
        onGranted()
    }
}

1
投票

它似乎以某种方式起作用。

package com.example.konretsca

import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.core.app.ActivityCompat
import com.example.konretsca.ui.theme.KonretscaTheme

fun debug (msg: String) {
    Log.d ("konretsca", msg)
}

class MainActivity : ComponentActivity() {

    override fun onCreate (savedInstanceState: Bundle?) {
        super.onCreate (savedInstanceState)
        debug ("onCreate")

        setContent {
            val permission =
                ActivityCompat.checkSelfPermission (
                    LocalContext.current,
                    Manifest.permission.CAMERA
                ) == PackageManager.PERMISSION_GRANTED
            var granted by remember { mutableStateOf (permission) }
            val launcher = rememberLauncherForActivityResult (ActivityResultContracts.RequestPermission()) {
                granted = it
            }

            if(!granted){
                SideEffect {
                    launcher.launch(Manifest.permission.CAMERA)
                }
            }
            else {
                KonretscaTheme {
                    Surface(
                        modifier = Modifier.fillMaxSize(),
                        color = MaterialTheme.colorScheme.background
                    ) {
                        Main()
                    }
                }
            }
        }
    }
}

@Composable
fun Main () {
    Text (text = "Main")
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview () {
    KonretscaTheme {
        Main ()
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.