@Entity Creature
I am attempting to update the name property in my database.
@Entity(primaryKeys = ["name"])
data class Creature(
@ColumnInfo(defaultValue = "New Creature") val name: String
)
@Dao CreatureDao
The query which updates the name is here, in the DAO.
@Dao
interface CreatureDao {
[...]
// update creature name
@Query("UPDATE Creature SET name=:newName WHERE name=:oldName")
fun updateCreatureName(oldName: String, newName: String)
}
MyRepository
My view model makes the query via my repository
class MyRepository(private val creatureDao: CreatureDao) {
[...]
// update creature name
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun updateCreatureName(oldName: String, newName: String) {
creatureDao.updateCreatureName(oldName, newName)
}
}
SharedViewModel
This is where my view model makes the call to update the name property
class SharedViewModel(
private val repository: MyRepository
) : ViewModel() {
[...]
fun updateCreatureName(oldName: String, newName: String) {
viewModelScope.launch { repository.updateCreatureName(oldName, newName) }
}
}
AboutFragment
This view model's updateCreatureName() method is called from AboutFragment when the nameTextInputEditText is changed...
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)
}
})
}
}
Problem
I receive error
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
When I try to launch the activity fragment. How can I run
override fun afterTextChanged()
off of the main thread?
CodePudding user response:
You could use a ExecutorService and then call the method submit()
passing a Runnable
. Create a single instance in you class or inject a Singleton in case you are using dependency injection.
Maybe the Jetpack framework is providing here some better ideas also.
CodePudding user response:
The key was to use
viewModelScope.launch(Dispatcher.IO){...}
instead of
viewModelScope.launch{...}
"When you don't pass a Dispatcher to launch, any coroutines launched from viewModelScope run in the main thread." source