简体   繁体   中英

How can I generate a String in a function in a viewmodel and return to a fragment in Kotlin?

I want to generate a String in a function in my viewmodel and send it to the fragment associated to this viewmodel as a LiveData, how can I do it?

For example, my viewmodel:

class MaskViewModel : ViewModel() {

    var mask: MutableLiveData<String> = newQuestion()

    fun newQuestion(): MutableLiveData<String>{

        mask.value="255"
        return mask
    }
}

And the observer in my fragment:

maskviewModel.mask.observe(viewLifecycleOwner){ result ->
            binding.textView3.text=result
        }

You appear to be all set up to observe any changes to your mask variable within your fragment. To set a new String to it, simply call mask.postValue(myString) within your function. This will trigger your observer, which will receive the new value of mask as result .

Additionally, you are not assigning an instance of MutableLiveData to mask . Your newQuestion() never creates an instance of MutableLiveData , but rather tries to access it while it is still null.

Instantiate it this way: val mask: MutableLiveData<String> = MutableLiveData() . Then you can call .postValue() on it. I've changed it to val because you can keep it as the same reference but still change the value within it. Keep it as var only if you wish to reassign it to a new MutableLiveData at some point, which is unlikely.

Your function should not return a LiveData or replace the existing LiveData. You should only have a single LiveData instance so when the Fragment observes it, it will get all future changes.

class MaskViewModel : ViewModel() {

    val mask = MutableLiveData<String>()

    fun newQuestion() {
        mask.value="255"
    }
}

But it is better encapsulation not to expose your LiveData as being mutable outside the class, so this is better:

class MaskViewModel : ViewModel() {

    private val _mask = MutableLiveData<String>()
    val mask: LiveData<String> get() = _mask

    fun newQuestion() {
        _mask.value="255"
    }
}

As @Tenfour04 mentions in his answer, your function should not return LiveData .

instead of returning the string from your viewModel , you could return it's id, and call the string from fragment.

in the ViewModel

private val _mask = MutableLiveData<Int>()
val mask: LiveData<Int> get() = _mask

fun newQuestion() {
        _mask.value = R.string.mask_value
    }

in the Fragment

maskviewModel.mask.observe(viewLifecycleOwner){ id ->
            binding.textView3.text = requireContext().getString(id)
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM