Android Jetpack Compose(可组合)从协程获取字符串资源

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

我有一个封装密封类的 Flow,用于向 UI 调用消息。例如显示 Snackbar。我可以使用 LaunchedEffect 观察可组合项的流程。但问题是我想从协程范围中检索字符串资源。我不想在视图模型中使用直接字符串值,因为我想使用不同语言的区域设置,所以我传递了字符串 Res Id。那么有没有一种好的方法可以做到这一点,而无需将字符串资源放入应用程序类中并从那里检索它们,如此处所示getString Outside of a Context or Activity

以下代码:

  1. 我有用于显示小吃栏的脚手架,当用户单击填充整个屏幕的脚手架时,将调用 showSnackbarWithScope 方法,该方法会向 Flow 发出新值。
  2. 然后通过 LaunchedEffect 捕获更改
  3. 然后它使用消息调用 showSnackbar() 方法,但该函数需要 String 并且我有 String Res Id (Int) 值
  4. 问题是我无法使用 stringResource() 方法从 Composable 范围中检索字符串,因为我位于协程中
@Composable
fun HomeScreen(viewModel: CityWeatherViewModel) {
 
    val scaffoldState = rememberScaffoldState() 
    LaunchedEffect(true) {
        viewModel.eventFlow.collectLatest { event ->
            when (event) {
                is CityWeatherViewModel.UIEvent.ShowSnackbar -> {
                    
                    // THE PROBLEM IS HERE!!!, since event.messageResId is res id, and not the string resource, and I can not use stringResource from coroutine
                    scaffoldState.snackbarHostState.showSnackbar(
                        message = event.messageResId
                    )
                }
            }
        }
    } 
 
    Scaffold(
        scaffoldState = scaffoldState,
        modifier = Modifier
            .fillMaxSize()
            .clickable {
                viewModel.showSnackbarWithScope(R.string.could_not_determine_location)
            }
    ) {

    }
}


@HiltViewModel
class CityWeatherViewModel @Inject constructor(
    private val getCityWeather: GetCityWeather
) : ViewModel() {

    // to show snackbar with error
    private val _eventFlow = MutableSharedFlow<UIEvent>()
    val eventFlow = _eventFlow.asSharedFlow()

     suspend fun showSnackbar(stringResId: Int) {
         _eventFlow.emit(
            UIEvent.ShowSnackbar(stringResId)
         )
     }

     fun showSnackbarWithScope(stringResId: Int) {
         viewModelScope.launch {
            showSnackbar(stringResId)
         }
         _eventFlowSwitch.value = !_eventFlowSwitch.value
    }

    sealed class UIEvent {
        data class ShowSnackbar(val messageResId: Int) : UIEvent()
    }

    companion object {

        // time in ms, before we request new data
        const val DELAY_BEFORE_REQUEST = 1500L
    }
}
android kotlin android-jetpack-compose android-jetpack-compose-scaffold
1个回答
31
投票

您可以使用

Context
在任何可组合项中获取
LocalContext
,然后在
LaunchedEffect
中使用它来获取资源:

val context = LocalContext.current
LaunchedEffect(Unit) {
    context.getString(event.messageResId)
}
© www.soinside.com 2019 - 2024. All rights reserved.