I have a Flow that wraps a sealed class, which is used for calling messages to the UI. For example to show a Snackbar. I can observe the Flow from a Composable using LaunchedEffect. But the problem is that I want to retrieve the string resources from the coroutine scope. And I don't want to use direct string value in my view model, since I want to use the Locale for different languages so I pass the String Res Id instead. So is there a good way of doing it without putting the string resources in the Application class and retrieving them from there as sujested here getString Outside of a Context or Activity
The code below:
@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
}
}
You can get Context
in any composable using LocalContext
and then use it inside LaunchedEffect
to get your resources:
val context = LocalContext.current
LaunchedEffect(Unit) {
context.getString(event.messageResId)
}