Open1

uiStateを更新する汎用拡張関数

るるすたるるすた

結論

UIの入力ごとに状態を更新しなければならないのであれば、
汎用的な関数を作っておきましょう!!!!

今までの状態更新

汎用関数はupdateUiStateです。
例えば、PersonUiStateの中で人物の状態を管理していたとする。
こんな感じの項目を編集する画面を想像。

その場合、以下のようになっているのではないでしょうか。

data class PersonUiState(
    val id:Int,
    val name:String,
    val age:Int,
    //以下すごくたくさんの管理項目
)

UI側の名前や年齢を編集したとき、viewModelの状態を更新する関数を
ひたすら以下のように作っていました。
(あほなん?って思われるかもですが。。。)

class PersonViewModel:ViewModel() {
    private val _uiState = MutableStateFlow(PersonUiState())
    val uiState: StateFlow<PersonUiState> = _uiState.asStateFlow()

    fun updateName(name: String){
        _uiState.update { it.copy(name = name) }
    }
    fun updateAge(age: String){
        _uiState.update { it.copy(age = age) }
    }
}

UIからの呼び出しはこう。

onValueChange ={ viewModel.updateName(it) }

入力フィールドがめっちゃたくさんあったらviewModelがめっちゃ長くなって
どこに何が書いてあるの!?ってなります。

汎用関数を作る

updateXXXX()関数を10個ぐらい作った時に、これ汎用化すればよいのでは?と気づきました🤮

    fun updateUiState(update: PersonUiState.() -> PersonUiState) {
        _uiState.update { it.update() }
    }

_uiState.update { it.copy() } この部分はまるっと引数から受け取ります。
なので、呼び出し側は以下のように記述します。

onValueChange ={ viewModel.updateUiState(update={copy(name = it)}) }

呼び出し側の記述が若干面倒ですが、fun updateXXXXをひたすらviewModelに
記述するよりはマシなのではないでしょうか。