我们知道LiveData 是生命周期感知的,如果配置更改 LiveData 对象不会每次都从数据库(本地/远程)重新查询,并且只有在数据中有任何更新时才会更新。
最近我开始使用Kotlin Flow,我应该承认它最适合数据层,即在 repo 中实现,以便通知 ViewModel。但是我在 ViewModel/View 层中也使用了Kotlin Flow,以便我collect
直接根据其状态(密封类实现)在 Fragment 中的 Flow 对象。我在使用 Flow 时遇到的问题是每次从数据库(本地/远程)检索配置更改数据时。
在这种情况下应该怎么做?有没有办法避免在使用 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