Android 房间 - 无法在主线程上访问数据库
Android Room - Cannot access database on the main thread
我收到“无法访问主线程上的数据库,因为它可能会长时间锁定 UI。”错误,但据我了解,我正在启动一个新的协同程序以将数据插入数据库。我做错了什么?
无线电活动:
val finishButton : Button = findViewById(R.id.radioFinishButton)
finishButton.setOnClickListener {
val radioName = findViewById<EditText>(R.id.radioName)
val radioUri = findViewById<EditText>(R.id.radioUri)
val replyIntent = Intent()
when {
TextUtils.isEmpty(radioName.text) -> radioName.error = "Radio name is required!"
TextUtils.isEmpty(radioUri.text) -> radioUri.error = "Radio URL is required!"
else -> {
replyIntent.putExtra(EXTRA_REPLY_NAME, radioName.text.toString())
replyIntent.putExtra(EXTRA_REPLY_URI, radioUri.text.toString())
setResult(Activity.RESULT_OK, replyIntent)
finish()
}
}
}
无线电片段:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val getResult = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
){
var name = ""
var uri = ""
if(it.resultCode == Activity.RESULT_OK){
it.data?.getStringExtra(RadioActivity.EXTRA_REPLY_NAME)?.let{ reply ->
name = reply
}
it.data?.getStringExtra(RadioActivity.EXTRA_REPLY_URI)?.let{ reply ->
uri = reply
}
Toast.makeText(context, "Name = ${name}, uri = ${uri}", Toast.LENGTH_LONG).show()
val radio = Radio(5, name, uri)
radioViewModel.insert(radio)
}else{
Toast.makeText(context, "Error while saving", Toast.LENGTH_LONG).show()
}
}
val recyclerView = view.findViewById<RecyclerView>(R.id.radioRecyclerView)
val adapter = RadioListAdapter()
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(context)
radioViewModel.radioList.observe(viewLifecycleOwner) {
it.let{
adapter.submitList(it)
}
}
}
无线电存储库:
val radioList: Flow<List<Radio>> = radioDao.getAll()
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun insert(radio: Radio) {
radioDao.insert(radio)
}
无线电模型:
fun insert(radio: Radio) = viewModelScope.launch {
repository.insert(radio)
}
尝试在 RadioRepository
中切换上下文:
suspend fun insert(radio: Radio) = withContext(Dispatchers.IO) {
radioDao.insert(radio)
}
您正在使用 @Suppress("RedundantSuspendModifier")
注释,它抑制了 RedundantSuspendModifier
错误。此错误意味着您的 insert
函数不是 suspend
并且将 运行ning 在调用它的线程中。
withContext(Dispatchers.IO)
切换协程的上下文,使 insert
函数在后台(工作)线程中变为 运行。
尝试在您的 viewmodelScope 上指定调度程序
fun insert(radio: Radio) = viewModelScope.launch(Dispatchers.IO) {
repository.insert(radio)
}
如果不起作用,请尝试使用 withContext
切换上下文
fun insert(radio: Radio) = viewModelScope.launch {
withContext(Dispatchers.IO) {
repository.insert(radio)
}
}
我收到“无法访问主线程上的数据库,因为它可能会长时间锁定 UI。”错误,但据我了解,我正在启动一个新的协同程序以将数据插入数据库。我做错了什么?
无线电活动:
val finishButton : Button = findViewById(R.id.radioFinishButton)
finishButton.setOnClickListener {
val radioName = findViewById<EditText>(R.id.radioName)
val radioUri = findViewById<EditText>(R.id.radioUri)
val replyIntent = Intent()
when {
TextUtils.isEmpty(radioName.text) -> radioName.error = "Radio name is required!"
TextUtils.isEmpty(radioUri.text) -> radioUri.error = "Radio URL is required!"
else -> {
replyIntent.putExtra(EXTRA_REPLY_NAME, radioName.text.toString())
replyIntent.putExtra(EXTRA_REPLY_URI, radioUri.text.toString())
setResult(Activity.RESULT_OK, replyIntent)
finish()
}
}
}
无线电片段:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val getResult = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
){
var name = ""
var uri = ""
if(it.resultCode == Activity.RESULT_OK){
it.data?.getStringExtra(RadioActivity.EXTRA_REPLY_NAME)?.let{ reply ->
name = reply
}
it.data?.getStringExtra(RadioActivity.EXTRA_REPLY_URI)?.let{ reply ->
uri = reply
}
Toast.makeText(context, "Name = ${name}, uri = ${uri}", Toast.LENGTH_LONG).show()
val radio = Radio(5, name, uri)
radioViewModel.insert(radio)
}else{
Toast.makeText(context, "Error while saving", Toast.LENGTH_LONG).show()
}
}
val recyclerView = view.findViewById<RecyclerView>(R.id.radioRecyclerView)
val adapter = RadioListAdapter()
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(context)
radioViewModel.radioList.observe(viewLifecycleOwner) {
it.let{
adapter.submitList(it)
}
}
}
无线电存储库:
val radioList: Flow<List<Radio>> = radioDao.getAll()
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun insert(radio: Radio) {
radioDao.insert(radio)
}
无线电模型:
fun insert(radio: Radio) = viewModelScope.launch {
repository.insert(radio)
}
尝试在 RadioRepository
中切换上下文:
suspend fun insert(radio: Radio) = withContext(Dispatchers.IO) {
radioDao.insert(radio)
}
您正在使用 @Suppress("RedundantSuspendModifier")
注释,它抑制了 RedundantSuspendModifier
错误。此错误意味着您的 insert
函数不是 suspend
并且将 运行ning 在调用它的线程中。
withContext(Dispatchers.IO)
切换协程的上下文,使 insert
函数在后台(工作)线程中变为 运行。
尝试在您的 viewmodelScope 上指定调度程序
fun insert(radio: Radio) = viewModelScope.launch(Dispatchers.IO) {
repository.insert(radio)
}
如果不起作用,请尝试使用 withContext
fun insert(radio: Radio) = viewModelScope.launch {
withContext(Dispatchers.IO) {
repository.insert(radio)
}
}