我正在使用Room创建一个简单的应用程序,我创建了一个DAO接口:
interface ItemDao {
@Insert(onConflict = IGNORE)
fun addItem(item: Item)
}
和存储库接口:
interface ItemRepository {
fun addItem(item: Item)
}
下面是函数的实现:
class ItemRepositoryImpl(
private val itemDao: ItemDao
) : ItemRepository {
override fun addItem(item: Item) = itemDao.addItem(item)
}
在ViewModel类中,我使用viewModelScope启动了一个协同程序:
class ItemViewModel @Inject constructor(
private val repo: ItemRepository
) : ViewModel() {
fun addItem(item: Item) = viewModelScope.launch(Dispatchers.IO) {
repo.addItem(item)
}
}
我在UI调用addItem
的时候,已经成功的将物品添加到Room了,现在的问题是,ItemDao接口里面的addItem函数是不是一定要设置为suspend函数,如果是的话,为什么呢?我真的很困惑。
编辑:
下面是我创建数据库示例的方法:
fun provideItemDb(
@ApplicationContext
context : Context
) = Room.databaseBuilder(
context,
ItemDb::class.java,
"item_table"
).build()
2条答案
按热度按时间tsm1rwdh1#
Suspend函数不是必需的,但是如果您不将这些函数标记为
suspend
,则它们会阻塞,因此在主线程上调用它们是不安全的。如果你正在使用协程,调用一个阻塞IO函数是安全的,但只有当你当前的CoroutineContext没有使用
Dispatchers.Main
时。你当前没有使用suspend
函数,因为你正在使用Dispatchers.IO
运行你的协程,所以函数是从主线程调用的。如果你使用协程,为了代码的简单,你应该总是把它们标记为
suspend
,这样函数就更容易和更通用了。想象一下,例如,你还想用新添加项的行ID更新LiveData。(你可以通过在DAO函数中返回一个Long来实现这一点。)如果在DAO中使用
suspend
,则函数可能是:如果在DAO中没有使用
suspend
,那么函数必须是以下更复杂的实现之一:现在想象一个函数想要执行一系列不同的操作,DAO的非挂起版本会导致ViewModel中的协程看起来非常混乱(因此容易出错)。
jvlzgdj92#
现在的问题是,是否必须将ItemDao接口中的addItem函数设置为suspend函数?
如果是,为什么?我真的很困惑。
您是否希望每次调用
IO
时都必须记住在协程中使用IO
上下文调用addItem
?或者您是否希望无论您从何处调用它,它都能正常工作(在IO线程上的协程中运行)?这就是为什么要将其设置为
suspend
* 并在调用中切换到IO
上下文。