Search code examples
androidkotlinrx-javaviewmodel

Get string resources in viewmodel


I need to show value in percent in TextView like "15 %" I do it in viewModel by this way and it works:

                    perfusionIndexValue.postValue(
                        list.lastOrNull()?.perfusionIndex?.takeIf {
                            it != PerfusionIndex.NO_DATA
                        }?.value?.toString().orEmpty() + " %"
                    )

but if i do it with resources:

                    perfusionIndexValue.postValue(
                        list.lastOrNull()?.perfusionIndex?.takeIf {
                            it != PerfusionIndex.NO_DATA
                        }?.value?.toString().orEmpty() + Resources.getSystem().getString(R.string.pi_percent)
                    )

I get

io.reactivex.rxjava3.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | android.content.res.Resources$NotFoundException: String resource ID #0x7f0e0081

How i can set text like "15 %"


Solution

  • In your case I see you need here Context.

    However, the Context of the Fragment or the Activity should not be passed into the ViewModel. Only use Application Context to get resources, ... or something related to Application in ViewModel.

    Here, if you are not using Hilt (or Dagger) then you should replace ViewModel() to AndroidViewModel(application) as below:

    class MyViewModel(application: Application): AndroidViewModel(application) {
        ...
    }
    

    If using Hilt, you can inject the Application Context via the @ApplicationContext annotation like below without having to extend AndroidViewModel():

    @HiltViewModel
    class MyViewModel @Inject constructor(
        @ApplicationContext private val context: Context
    ): ViewModel() {
    
    }
    

    Here I note when using Hilt to inject Application Context into the ViewModel. You will see a warning about memory leak when injecting the Application Context into the ViewModel. This is a warning in the recent Hilt version, but I have tested Profiler and there is no leak.

    And you can get resource as string resource in ViewModel by calling:

    val myText = context.getString(R.string.your_string_id)