kotlin 存储库类内的协同程序作用域

zpjtge22  于 2023-01-31  发布在  Kotlin
关注(0)|答案(3)|浏览(178)

让我们假设我有一个Dto列表,我想遍历它们并设置一些值,然后将它们插入/更新到我的Room数据库中。因此,从我的ViewModel调用repository类,在其中运行循环,然后调用dao.insertItems(list)。

fun updateItems(itemList: List<ItemDto>) {
        val readDate = DateUtils.getCurrentDateUTCtoString()
        ???SCOPE???.launch(Dispatchers.IO) {
            for (item in itemList)
                item.readDate = readDate
            itemDao.updateItems(itemList)
        }
    }

问题是我必须在Repository类中使用什么类型的courtineScope。我必须用Dispatchers.Main..创建一个repositoryScope吗?也许是一个GlobalScope..?

wecizke3

wecizke31#

您应该将存储库API编写为suspend函数,如下所示

suspend fun updateItems(itemList: List<ItemDto>) = withContext(Dispatchers.IO) {
    val readDate = DateUtils.getCurrentDateUTCtoString()
    for (item in itemList)
        item.readDate = readDate
    itemDao.updateItems(itemList)
}

编辑:如果您需要它在视图模型被破坏后仍然运行,请使用NonCancellable启动它,

suspend fun updateItems(itemList: List<ItemDto>) = withContext(Dispatchers.IO + NonCancellable) {
    val readDate = DateUtils.getCurrentDateUTCtoString()
    for (item in itemList)
        item.readDate = readDate
    itemDao.updateItems(itemList)
}
l2osamch

l2osamch2#

在存储库中创建方法suspend fun并使用withContext(Dispatchers.IO)
例如:

suspend fun updateItems() = withContext(Dispatchers.IO) {
    //you work...
}
5vf7fwbs

5vf7fwbs3#

您应该默认使用存储库中的suspend函数,您可以使用viewModelScope从视图模型调用这些函数。

class MyRepository(
  private val itemDao: ItemDao,
  private val ioDispatcher: CoroutineDispatcher,
) {
  suspend fun updateItems(itemList: List<ItemDto>) {
    withContext(ioDispatcher) {
      val readDate = DateUtils.getCurrentDateUTCtoString()
      for (item in itemList) {
        item.readDate = readDate
        itemDao.updateItems(itemList)
      }
    }
  }
}

class MyViewModel(private val repository: MyRepository) : ViewModel() {
  fun updateItems() {
    viewModelScope.launch {
      repository.updateItems()
    }
  }
}

如果您需要一个不应该被视图模型取消的操作,那么在应用程序中创建一个作用域,并将其注入到您的存储库中。

class MyRepository(
  private val itemDao: ItemDao,
  private val externalScope: CoroutineScope,
  private val ioDispatcher: CoroutineDispatcher,
) {
  suspend fun updateItems(itemList: List<ItemDto>) {
    withContext(ioDispatcher) {
      val readDate = DateUtils.getCurrentDateUTCtoString()
      externalScope.launch(externalScope.coroutineContext) {
        for (item in itemList) {
          item.readDate = readDate
          itemDao.updateItems(itemList)
        }
      }
    }
  }
}

class MyApplication : Application() {
  // No need to cancel this scope as it'll be torn down with the process
  val applicationScope = CoroutineScope(SupervisorJob() + otherConfig)
}

不要使用NonCancellable,除非你想暂停清理代码。使用NonCancellable是非常危险的,因为你失去了对协程执行的控制。它可能导致微妙的,非常难以调试的错误。
如果使用的是Hilt,请按如下方式插入作用域:https://medium.com/androiddevelopers/create-an-application-coroutinescope-using-hilt-dd444e721528

相关问题