MutableListのMutableLiveDataではなくListのMutableLiveDataにする

MutableLiveData<MutableList<Int>>

のようなLiveDataを使う場合、MutableListaddメソッドなど要素を追加・削除するメソッドを呼び出して 更新しても、データの更新は通知されない。

以下のようなリストのLiveDataを持つViewModelを用意し、

class FooViewModel : ViewModel() {
  val list = MutableLiveData<MutableList<Int>>(mutableListOf())

  fun add(num: Int) {
    list.value.add(num)
  }

  fun remove(num: Int) {
    list.value.minus(num)
  }
}

Fragmentでリストをobserveする。

class FooFragment : Fragment() {
  private val viewModel : FooViewModel by viewModels()

  fun onCreateView(...) {
    viewModel.list.observe(viewLifecycleOwner) {
       // viewModel.list が更新されたときに実行する処理
    }  
  }
}

FooViewModeladdremoveが呼ばれるとlistvalueが変更されるが、上記observeには通知されない。

LiveDatapostValuesetValueが呼ばれたときに変更を通知するが、 破壊的メソッドを呼び出してもvalueに入っている参照が変わらないのでsetValueが呼び出されないため。

add、minusメソッドが使えないならLiveDataにする

LiveDataとしての旨味がないのでMutableListではなくただのListにする。

class FooViewModel : ViewModel() {
  val list = MutableLiveData<List<Int>>(emptyListOf())

  ...
}

Listだとadd、minusが使えないことへの対策

immutableなListクラスにしたことでaddminusメソッドが使えなくなったので 更新メソッドを非破壊のメソッドを使って以下のように書き換える。

class FooViewModel : ViewModel() {
  val list = MutableLiveData<MutableList<Int>>(mutableListOf())

  fun add(num: Int) {
    list.value = (list.value ?: emptyList()) + num
  }

  fun remove(num: Int) {
    list.value = (list.value ?: emptyList()) - num
  }
}

これでlist.valueへの代入となり、setValueが呼ばれることになり、LiveDataとしての通知がしっかり行なわれる。