Как смапить одну LiveData к другой

Я пытаюсь, следуя принципам UDF, отображать/менять состояние экрана через класс State. Я получаю данные из БД(Room) -> repository -> useCase во ViewModel и там пытаюсь смапить эти данные(одну LiveData к другой LiveData), но не получается. Подскажите что не так. Попробовал сделать тестовую переменную categoryTest и подписаться на неё - все работает, данные во фрагмент приходят и список заполняется. Из этого делаю вывод что проблема кроется где-то внутри MediatorLiveData().apply, но может где-нибудь ещё.

class MenuViewModel @Inject constructor(
private val loadCategoryUseCase: LoadCategoryUseCase,
private val getListCategoryUseCase: GetListCategoryUseCase
) : ViewModel() {

private val _categories = MutableLiveData<StateMenuFragment>()
val categories: LiveData<StateMenuFragment>
    get() = _categories

val categoryTest = getListCategoryUseCase() // Тестовая переменная

init {
    viewModelScope.launch {
        loadCategoryUseCase()
    }
    getCategories()
}

private fun getCategories() {
    _categories.value = StateMenuFragment(loading = true)
    viewModelScope.launch {
        try {
            val result = getListCategoryUseCase() // Возвращает объект типа LiveData<List<Category>>

            MediatorLiveData<StateMenuFragment>().apply {
                addSource(result) { categoryList ->
                    val updatedState = _categories.value?.copy(result = categoryList )
                        ?: StateMenuFragment(result = categoryList )

                    _categories.value = updatedState
                }
            }

        } catch (e: IOException) {
            if (_categories.value == StateMenuFragment(result = emptyList())) {
                _categories.value = StateMenuFragment(
                    error = ErrorMessage(isError = true, errorMessage = "error message")
                )
            }
        }
    }
}
}

Во фрагменте подписываюсь на них. Но список не приходит

   class MenuFragment : Fragment() {

   private fun updateState() {
        viewModel.categories.observe(viewLifecycleOwner) {
            binding.progressBar.visibility = View.GONE
            if (it.loading) {
                binding.progressBar.visibility = View.VISIBLE
            }
            if (it.error.isError) {
                Toast.makeText(requireContext(), it.error.errorMessage, Toast.LENGTH_SHORT). apply {
                    setGravity(Gravity.CENTER, 0, 0)
                }.show()
            }
            menuAdapter.submitList(it.result)
        }
       // Подписываюсь напрямую, миную класс State - данные приходят
       viewModel.categoryTest.observe(viewLifecycleOwner) {
            menuAdapter.submitList(it)
        }
    }
}

Класс state

data class StateMenuFragment(
    var result: List<Category> = emptyList(),
    val loading: Boolean = false,
    val error: ErrorMessage = ErrorMessage()
)
data class ErrorMessage(
    val isError: Boolean = false,
    val errorMessage: String = ""
)

Класс model

data class Category (
    val id: Int,
    val title: String,
    val imageUrl: String
)

Ответы (2 шт):

Автор решения: Wlad

верно думаете, проблема в MediatorLiveData
код, внутри нее, будет выполняться только когда на медиатор кто-то подпишется. а у вас никто на нее не подписан.

вы можете переделать свой код так, чтобы внутри ВьюМодели подписаться на Медиатор, используя mediator.observeForever(observer)
но тогда стоит не забыть и убрать слушателя с него, при уничтожении ВьюМодели

override fun onCleared() {
  mediator.removeObserver(observer)
  super.onCleared()
 }
→ Ссылка
Автор решения: woesss

Проблема не в apply, а в том что его вообще не должно быть.
Вы создали объект медиатора, но никуда его не применили, даже ссылку не сохранили.
Нужно присвоить медиатор свойству - тогда вы подпишетесь на него из фрагмента и получите свои данные:

private val _categories = MediatorLiveData<StateMenuFragment>()
...
private fun getCategories() {
...
            val result = getListCategoryUseCase() // Возвращает объект типа LiveData<List<Category>>

            _categories.addSource(result) { categoryList ->
                val updatedState = _categories.value?.copy(result = categoryList )
                    ?: StateMenuFragment(result = categoryList )

                _categories.value = updatedState
            }
→ Ссылка