#やったこと
Firebase Authenticationで作成したアカウントを、ユーザーが削除できる機能を作りました。その際削除が成功したかによってToastを表示したいと思い以下のように実装しました。
1 Repositoryでアカウントを削除
2 ViewModelの isDeleteUser : Flow に削除が成功したかを格納
3 Fragmentで isDeleteUser : Flow の値を収集してToast表示
Repository
//削除が成功したかどうかを受け取ってViewModelに返します
suspend fun deleteUser(): Boolean {
val result = deleteUserFun().getOrThrow()
if(result) return true
else {
Log.e("Error", result.toString())
return false
}
}
//実際のアカウント削除の処理
private suspend fun deleteUserFun(): Result<Boolean> {
return kotlin.runCatching {
suspendCoroutine { continuation ->
user.delete()
.addOnSuccessListener {
continuation.resume(true)
}
.addOnFailureListener {
continuation.resumeWithException(it)
}
}
}
}
ラムダ式を使ってViewModelに値を返すこともできるのですが、コールバック形式は美しくないのでsuspend関数で値を返していきます。
コールバックをsuspend関数でなくす方法についての参考にした記事
https://star-zero.medium.com/callback%E5%BD%A2%E5%BC%8F%E3%81%AE%E3%82%82%E3%81%AE%E3%82%92coroutines%E3%81%AB%E5%AF%BE%E5%BF%9C%E3%81%99%E3%82%8B-9384dfa6ad77
ViewModel
private val _isDeleteUser = MutableSharedFlow<Boolean>()
val isDeleteUser: Flow<Boolean> = _isDeleteUser
fun callDeleteUser() {
viewModelScope.launch(Dispatchers.IO) {
val result = Repository.repository.deleteUser()
_isDeleteUser.emit(result)
}
}
deleteUser()はsuspend関数で、suspend関数はcoroutineボディ内か他のsuspend関数内からしか呼び出せないのでこのようにしています。resultにdeleteUser()の返り値であるBooleanが格納された後
_isDeleteUser.emit(result)
とすることでMutableSharedFlowに値を送信しています。
また↓このようにしている理由ですが、MutableSharedFlowは再代入が可能なのでFragmentから参照する値をFlowにすることで再代入されることを防いでいます。
private val _isDeleteUser = MutableSharedFlow<Boolean>()
val isDeleteUser: Flow<Boolean> = _isDeleteUser
Fragment
viewLifecycleOwner.lifecycleScope.launch {
viewModel.isDeleteUser.collect {
// itにBooleanが入ってます
if (it) Toast.makeText(context, "アカウントを削除しました", Toast.LENGTH_LONG).show()
else Toast.makeText(
context,
"アカウントを削除できませんでした。再度ログイン後削除してください",
Toast.LENGTH_LONG
).show()
}
}
Flow.collectで値を収集し分岐してToastを表示させています。またcollectもcoroutineかsuspend関数から呼び出す必要があります。
#まとめ
emit()で値を送る
collect()で値を収集
#最後に
すごく具体的な使い方の解説になりました。Flowについての理解が深まったら凡庸的な使い方についても解説するかもしれません。助言、訂正すべき箇所などあったらどしどしコメントください!!