
【Android】備忘録その1(LiveData)
2022.05.17
LiveDataの値がDataBindingのLayoutに反映されない
Androidの勉強や実装中に気づいたこと忘れそうなことを自分用の備忘録として残していきたい。
初回はLiveDataを使うときに毎回忘れてしまって時間を無駄にすることを残しておく。
だいたいLifecycleOwnerの設定忘れている。
新規画面実装でよく忘れる。
1 2 3 4 5 6 7 8 9 10 | class MyFragment() : Fragment() { private lateinit var binding: FragmentLayoutBinding override fun onViewCreated(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { binding = FragmentLayoutBinding.inflate(inflater, container, false) // ↓これを毎回忘れる↓ binding.lifecycleOwner = viewLifecycleOwner // Activityはthis binding.vm = viewModel // ←当然Modelの設定忘れてはいけない return binding.root } } |
LiveDataの型と初期値は意識したほうがいい
気にしていないとハマる。
LiveDataの初期値はなるべく設定しておいたほうが不具合入り込みにくい気がする。
よくやってしまうのが処理結果をLiveDataで保持する場合↓ような持ち方をしてしまう。
1 | val resultModelLiveData = MutableLiveData<ResultModel>() |
これだと初期値の設定がしづらい。
初期値の設定がなくても実装できるが、画面のリセットがある実装やMediatorLiveData発火元の(addSoruceに追加する)LiveDataにする場合に、どうしても無理をした実装になってしまう。
また、「DroidKaigi2020アプリのcombine」を使う場合も、初期値があったほうが都合がいいことが多い(初期値がないとblockが実行されない実装になっているので)
解決方法は「ありえる状態をすべて表せるようにする」
以下のようなクラスをつくりラッピングして持つと扱いやすい。
1 2 3 4 5 6 7 | sealed class Status<out T> { object None: Status<Nothing>() object Loading: Status<Nothing>() object Canceled: Status<Nothing>() // ←Noneがあるので不要かもしれない class Succeeded<out T>(val value: T): Status<T>() class Failed(val e: Exception): Status<Nothing>() } |
(「Status」という名前でいいのかなぁ…もっといい名前ないかなという問題は残っている)
1 | val resultModelLiveData = MutableLiveData<Status<ResultModel>>(Status.None) |
↑のように初期値を表現できて、使いやすくて分かりやすいのでよき
他の解決策も一応ある
型をnullableにするのもアリですが場合によるかなぁと。nullが何を示しているか分かりづらいときもあるので、ラッピングする選択肢があることを忘れたくはない。
書いた人はこんな人
