I get the 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 run Code A, why?
The Code B can work well when I replace with fun add(aMVoice: MVoice)=viewModelScope.launch (Dispatchers.IO){}, why?
The Code C can work well when I replace with suspend fun add(aMVoice: MVoice), why?
And more, which one is better between Code B and Code C?
Code A
@Dao
interface DBVoiceDao{
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun add(aMVoice: MVoice)
}
class DBVoiceRepository private constructor(private val mDBVoiceDao: DBVoiceDao){
suspend fun add(aMVoice: MVoice){
mDBVoiceDao.add(aMVoice)
}
}
class HomeViewModel(private val mDBVoiceRepository: DBVoiceRepository) : ViewModel() {
fun add(aMVoice: MVoice)=viewModelScope.launch{
mDBVoiceRepository.add(aMVoice)
}
}
class FragmentHome : Fragment() {
private val mHomeViewModel by lazy {...}
...
btnInsert.setOnClickListener {
val aMVoice = MVoice()
mHomeViewModel.add(aMVoice)
}
...
}
Code B
@Dao
interface DBVoiceDao{
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun add(aMVoice: MVoice)
}
class DBVoiceRepository private constructor(private val mDBVoiceDao: DBVoiceDao){
suspend fun add(aMVoice: MVoice){
mDBVoiceDao.add(aMVoice)
}
}
class HomeViewModel(private val mDBVoiceRepository: DBVoiceRepository) : ViewModel() {
fun add(aMVoice: MVoice)=viewModelScope.launch (Dispatchers.IO){ //I add Dispatchers.IO
mDBVoiceRepository.add(aMVoice)
}
}
class FragmentHome : Fragment() {
private val mHomeViewModel by lazy {...}
...
btnInsert.setOnClickListener {
val aMVoice = MVoice()
mHomeViewModel.add(aMVoice)
}
...
}
Code C
@Dao
interface DBVoiceDao{
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun add(aMVoice: MVoice) //I add suspend
}
class DBVoiceRepository private constructor(private val mDBVoiceDao: DBVoiceDao){
suspend fun add(aMVoice: MVoice){
mDBVoiceDao.add(aMVoice)
}
}
class HomeViewModel(private val mDBVoiceRepository: DBVoiceRepository) : ViewModel() {
fun add(aMVoice: MVoice)=viewModelScope.launch {
mDBVoiceRepository.add(aMVoice)
}
}
class FragmentHome : Fragment() {
private val mHomeViewModel by lazy {...}
...
btnInsert.setOnClickListener {
val aMVoice = MVoice()
mHomeViewModel.add(aMVoice)
}
...
}
}