将Coroutine调用放在存储库或ViewModel中哪个更好?

时间:2019-03-13 15:39:50

标签: android mvvm kotlin android-room coroutine

只是想问别人我有两种方法可以做某事,而且很好奇(希望您为什么这么想)

我有2个文件WordRepository和WordViewModel。我既可以在Repo中也可以在ViewModel中进行协同程序工作,但是希望有人可以为我提供一个线索,让我解释为什么我要在一个或另一个中进行协同程序,反之亦然。

版本A。(协程位于回购中)

WordRepo:

class WordRepository(private val wordDao: WordDao): WordRepo {

    @WorkerThread
    override suspend fun deleteAllLogsOlderThan(XDays: Int): Int = withContext(IO) {
        return@withContext wordDao.deleteAll()
    }

}

WordViewModel:

class WordViewModel(private val wordRepository: WordRepo) : ViewModel() {

    fun deleteAllLogsOlderThanA(XDays:Int): Int = runBlocking {
        wordRepository.deleteAllLogsOlderThan(XDays)
    }

}

版本B。(协程位于ViewModel中)

Word Repo:
class WordRepository(private val wordDao: WordDao): WordRepo {

    @WorkerThread
    override suspend fun deleteAllLogsOlderThan(XDays: Int): Int = wordDao.deleteAll()

}

WordViewModel:
class WordViewModel(private val wordRepository: WordRepo) : ViewModel() {

    fun deleteAllLogsOlderThanA(XDays:Int): Int = runBlocking {
            withContext(IO) {
                wordRepository.deleteAllLogsOlderThan(XDays)
            }
        }

}

2 个答案:

答案 0 :(得分:0)

我认为任何一种方法都可以,但是如果我必须选择,我宁愿将与线程相关的代码保留在存储库层中。 (示例中为版本A

我的辩解:

(A)视图模型不应假定存储库在内部如何工作。 版本B 表示视图模型假定存储库将在调用线程上运行。

(B)此外,存储库不应依赖其他组件来使用特定线程来调用其方法。该存储库应本身完整。

(C)为避免代码重复。具有多个View模型调用一个存储库方法是一种很常见的情况。在这种情况下,版本A 会获胜,因为您只需要在仓库中一个地方Corountine


我建议查看一些Google样本,以了解他们希望在哪里处理Coroutine和数据访问线程代码。

  1. Sunflower在其存储库中使用Coroutine代码。这可能对您特别有用,因为它包含了“一劳永逸”类型的请求示例。

  2. GitHubBrowserRepo不使用Coroutine,但是存储库保留对访问数据时使用的Executor实例的引用。

答案 1 :(得分:0)

问题是在哪里指定存储库作业应在IO线程池上运行:

  • A)在存储库中
  • B)在ViewModel中

坦率地说,我不确定哪种方法更好。

B)在ViewModel中使用它意味着在哪个线程上运行的内容更加透明。这也是我主要使用RxJava的方式。否定的是,您的ViewModel会因线程切换(withContext())而变得混乱,而实际上很明显,所有存储库作业都应在后台线程上运行。那么这些额外的信息有用吗?

A)在存储库中拥有它意味着在存储库中的线程切换和ViewModel中的更干净的代码方面具有更大的灵活性。从ViewModel角度来看,有关线程的代码将不太明确。不利的是,所有存储库方法都需要暂停,因此只能在协程中使用。