LiveDataはライフサイクルに対応しており、構成が変更された場合、LiveData オブジェクトは毎回データベース (ローカル/リモート) から再クエリを実行せず、データに更新がある場合にのみ更新されます。
最近、私はKotlin Flowを使い始めました。データ層、つまり ViewModel に通知されるようにリポジトリに実装するのに最適であることを認めなければなりません。しかし、ViewModel/View レイヤーでもKotlin Flowを使用して、Fragment 内の Flow オブジェクトをそのStatus (sealed class implementation)collect
に直接基づいて直接作成しました。このフローの使用法で私が遭遇した問題は、構成変更データがデータベース (ローカル/リモート) から取得されるたびに発生することです。
この場合、どうすればよいですか?Flow の使用中に再クエリを回避する方法はありますか、または ViewModel/View Layer で LiveData のみを使用する必要がありますか?
サンプルコード
sealed class Status<T> {
class Processing<T> : Status<T>()
data class Completed<T>(val value: T) : Status<T>()
data class Error<T>(val error: String) : Status<T>()
companion object {
fun <T> processing() = Processing<T>()
fun <T> completed(value: T) = Completed(value)
fun <T> error(error: String) = Error<T>(error)
}
}
レポ:
class Repo(database: LocalDatabase){
fun retrieveUsersData() = flow<Status<List<Users>>>{
emit(Status.processing())
database.dao.getUsers().collect{
// Assume db queries successfully and returns list of users
emit(Status.completed(it))
}
}.catch {
emit(Status.error(it.error.toString()))
}.flowOn(Dispatchers.IO)
}
ビューモデル:
class MyViewModel(application: Application): AndroidViewModel(application)
{
private val db = LocalDatabase.getInstance(application)
private val repo = Repo(db)
val usersData= repo.retrieveUsersData(dataCollectionType)
}
断片:
class UsersFragment: Fragment(){
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Assume all the declarations are done properly
coroutineScope.launch {
retrieveUsersData()
}
}
private suspend fun retrieveUsersData(){
viewModel.retrieveUsersData().collect{ status ->
// Based on the Status do the actions.
// When Status is Completed set the data to the adapter.
}
}
} // end of Fragment