如何运行 afterTextChanged 关闭主线程?
How to Run afterTextChanged off of the main thread?
@实体生物
我正在尝试更新数据库中的名称 属性。
@Entity(primaryKeys = ["name"])
data class Creature(
@ColumnInfo(defaultValue = "New Creature") val name: String
)
@Dao CreatureDao
更新名称的查询在此处,在 DAO 中。
@Dao
interface CreatureDao {
[...]
// update creature name
@Query("UPDATE Creature SET name=:newName WHERE name=:oldName")
fun updateCreatureName(oldName: String, newName: String)
}
我的资料库
我的视图模型通过我的存储库进行查询
class MyRepository(private val creatureDao: CreatureDao) {
[...]
// update creature name
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun updateCreatureName(oldName: String, newName: String) {
creatureDao.updateCreatureName(oldName, newName)
}
}
SharedViewModel
这是我的视图模型调用更新名称的地方属性
class SharedViewModel(
private val repository: MyRepository
) : ViewModel() {
[...]
fun updateCreatureName(oldName: String, newName: String) {
viewModelScope.launch { repository.updateCreatureName(oldName, newName) }
}
}
关于片段
当 nameTextInputEditText 更改时,从 AboutFragment 调用此视图模型的 updateCreatureName() 方法...
class AboutFragment() : Fragment() {
[...]
// update creature record when creature name is edited
binding.nameTextInputEditText.addTextChangedListener(object : TextWatcher {
private lateinit var oldName: String
private lateinit var newName: String
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
oldName = s.toString()
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
newName = s.toString()
}
override fun afterTextChanged(s: Editable?) {
sharedViewModel.updateCreatureName(oldName, newName)
}
})
}
}
问题
我收到错误
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
当我尝试启动 activity 片段时。我怎样才能运行
override fun afterTextChanged()
关闭主线程?
您可以使用 ExecutorService,然后调用传递 Runnable
的方法 submit()
。在你 class 中创建一个实例,或者在你使用依赖注入的情况下注入一个单例。
也许 Jetpack 框架在这里也提供了一些更好的想法。
关键是使用
viewModelScope.launch(Dispatcher.IO){...}
而不是
viewModelScope.launch{...}
"When you don't pass a Dispatcher to launch, any coroutines launched
from viewModelScope run in the main thread."
source
@实体生物
我正在尝试更新数据库中的名称 属性。
@Entity(primaryKeys = ["name"])
data class Creature(
@ColumnInfo(defaultValue = "New Creature") val name: String
)
@Dao CreatureDao
更新名称的查询在此处,在 DAO 中。
@Dao
interface CreatureDao {
[...]
// update creature name
@Query("UPDATE Creature SET name=:newName WHERE name=:oldName")
fun updateCreatureName(oldName: String, newName: String)
}
我的资料库
我的视图模型通过我的存储库进行查询
class MyRepository(private val creatureDao: CreatureDao) {
[...]
// update creature name
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun updateCreatureName(oldName: String, newName: String) {
creatureDao.updateCreatureName(oldName, newName)
}
}
SharedViewModel
这是我的视图模型调用更新名称的地方属性
class SharedViewModel(
private val repository: MyRepository
) : ViewModel() {
[...]
fun updateCreatureName(oldName: String, newName: String) {
viewModelScope.launch { repository.updateCreatureName(oldName, newName) }
}
}
关于片段
当 nameTextInputEditText 更改时,从 AboutFragment 调用此视图模型的 updateCreatureName() 方法...
class AboutFragment() : Fragment() {
[...]
// update creature record when creature name is edited
binding.nameTextInputEditText.addTextChangedListener(object : TextWatcher {
private lateinit var oldName: String
private lateinit var newName: String
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
oldName = s.toString()
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
newName = s.toString()
}
override fun afterTextChanged(s: Editable?) {
sharedViewModel.updateCreatureName(oldName, newName)
}
})
}
}
问题
我收到错误
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
当我尝试启动 activity 片段时。我怎样才能运行
override fun afterTextChanged()
关闭主线程?
您可以使用 ExecutorService,然后调用传递 Runnable
的方法 submit()
。在你 class 中创建一个实例,或者在你使用依赖注入的情况下注入一个单例。
也许 Jetpack 框架在这里也提供了一些更好的想法。
关键是使用
viewModelScope.launch(Dispatcher.IO){...}
而不是
viewModelScope.launch{...}
"When you don't pass a Dispatcher to launch, any coroutines launched from viewModelScope run in the main thread." source