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:
- I have Scaffold for showing snackbar, when the user clicks the scaffold which fills the whole screen the showSnackbarWithScope method is called, which emits new value to the Flow.
- Then the change is catch through the LaunchedEffect
- Then it calls the showSnackbar() method with the message, but the function expects String and I have String Res Id (Int) value
- The problem I cannot use stringResource() method which retrieves the string from Composable scope, since I am in a coroutine
@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
    }
}
 
    