视图、视图模型、用例、存储库、服务和 dao 之间的通信流

问题描述 投票:0回答:0

使用

monarchy realm
数据库,
dao
给出
liveData.
A
repository
liveData
提供给
useCase
作为
flow
使用
.asFlow
上的
liveData.
useCase 
需要在进行一些
flow
ViewModel
和其他验证后,将
filter,
返回到
map,
ViewModel
flow
收集
useCase
并将更新发布到本地
mutableLiveData.
A
view
观察
liveData
mutableLiveData.
形式
View
接收更新!

//fragment.kt
fun initObserver() {
    viewModel.itemsLiveData.observe(viewLifeCycleOwner) { list ->
        onUpdateItems(list)
    }
}

//viewModel.kt
private val _itemsLiveData = MutableLiveData<List<Items>>()
val itemsLiveData = _itemsLiveData

init {
    getItems()
}

fun getItems() {
    viewModelScope.launch(Dispatchers.IO) {
        useCase.getItems().collectLatest { items ->
            _itemsLiveData.postValue(items)
        }
    }
}

//usecase.kt (callbackFlow or suspendCancellableCoroutine?)
suspend fun getItems(): callbackFlow<List<Items>> {
    repository.getItems().collectLatest { dbItems ->
        val validList = dbItems.filter { it.isValid() }.map { it.toUiModel() }
        if (validList.isNotEmpty()) {
            trySendBlocking(validList)
        } else {
            trySendBlocking(defaultList)
        }
    }
    
    //Cancel this coroutine scope and it's children.
    awaitClose {
        cancel()
    }
    
    //Close this channel. No more sending. Sending operation is closed.
    channel.close()
}

suspend fun apiCall() {
    val result = api.getItems()
    if (result.isSuccessful) {
        val items = result.body()?.items
        if (items != null && items.isNotEmpty()) {
            repository.saveItems(items)
        }
    }
}

//repository.kt
suspend fun getItems() = withContext(Dispatchers.Main) { dao.getItemsLiveData().asFlow() }
suspend fun saveItems(items: Items) = withContext(Dispatchers.Main) { dao.saveItems(items) }

//dao.kt
fun getItemsLiveData() = LiveData<Items>()
fun saveItems(items: Items)

但是,我有几个问题或疑问:

  1. 是否会导致内存泄漏?
  2. 我是否以正确的方式使用
    flow
  3. 我应该在
    take(1)
    中的
    first()
    上使用
    repository.getItems()
    还是
    useCase
  4. 当数据库中没有数据时,我们返回默认值。当用户打开关联的屏幕或执行
    pull To Refresh,
    操作时,我们将进行 API 调用并将数据保存到数据库中。我相信更新将按以下顺序进行:从数据库到
    repository,
    useCase,
    ViewModel,
    fragment.
    但我怀疑
    useCase
    ,因为它取消了范围并关闭了通道。我怀疑它不会收到任何更新,直到我们再次调用
    useCase.getItems
    再次,开始从
    repository.
    收集流量,是吗?如果是,我们如何设置整个通信,以便每当数据库发生更改时
    fragment
    始终收到更新,而无需在进行 API 调用后再次调用
    useCase.getItems
    函数?
  5. 对于这样的要求,我应该使用
    suspendCancellableCoroutine
    而不是
    callbackFlow
    吗?
android android-livedata clean-architecture kotlin-flow android-mvvm
© www.soinside.com 2019 - 2024. All rights reserved.