Android 观察从后台线程进行的数据库对象更改

Android 观察从后台线程进行的数据库对象更改,android,android-room,Android,Android Room,我在应用程序中观察数据时遇到问题 出于测试目的,我有一个带有单个文本视图的活动,其中显示了用户名。代码如下: @Entity(tableName = "User") data class User( var name: String, var surname: String, @PrimaryKey(autoGenerate = true) val internalID: Long = 0) 在dao中,我只有一种方法: @Query("SELECT * FRO

我在应用程序中观察数据时遇到问题

出于测试目的,我有一个带有单个文本视图的活动,其中显示了用户名。代码如下:

@Entity(tableName = "User")
data class User(
    var name: String,
    var surname: String,
    @PrimaryKey(autoGenerate = true)
    val internalID: Long = 0)
在dao中,我只有一种方法:

@Query("SELECT * FROM User WHERE surname LIKE :surname")
abstract suspend fun getUserForSurname(surname: String): User
在activity onCreate的方法中:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
    val model = ViewModelProvider(this).get(MainViewModel::class.java)
    binding.viewmodel = model
    model.user.observe(this, Observer {
        binding.textTest.setText(it.name)
    })
}
最后,查看模型:

class MainViewModel(application: Application) : AndroidViewModel(application) {

    private val surname = "Doe"
    val user: MutableLiveData<User> = MutableLiveData()
    private val userDao: UserDao =
        MyRoomDatabase.getDatabase(application).clientDao()

    init {
        viewModelScope.launch {
            user.value = userDao.getUserForSurname(surname)
        }
    }
}
class MainViewModel(应用程序:应用程序):AndroidViewModel(应用程序){
私人val姓氏=“Doe”
val用户:MutableLiveData=MutableLiveData()
私有val userDao:userDao=
MyRoomDatabase.getDatabase(应用程序).clientDao()
初始化{
viewModelScope.launch{
user.value=userDao.getUserForSurname(姓氏)
}
}
}

该特定用户名在后台线程中更改。当我检查db本身中的值时,名称确实不同。重新启动“活动”后,文本视图也将更改。换言之:db值已更改,但从未调用观察者。我知道我在viewmodel的init方法中只请求了一次值,这可能是个问题。是否可以在不重新启动活动的情况下看到实际的更改?

我建议您查看一下

文件室在返回的实体周围显示不同的包装,例如:

  • RxJava
  • 流协同路由
  • 实时数据
因此,您可以将Dao更改为:

@Query("SELECT * FROM User WHERE surname LIKE :surname")
abstract fun getUserForSurname(surname: String): LiveData<User>
@Query(“从用户中选择*,如:姓氏”)
抽象趣味getUserForSurname(姓氏:String):LiveData
上面的意思是,对用户条目的任何更改都将向LiveData的侦听器发出一个观察结果

视图模型

class MainViewModel(application: Application) : AndroidViewModel(application) {

    private val surname = "Doe"
    lateinit val client: LiveData<User>
    private val userDao: UserDao =
        MyRoomDatabase.getDatabase(application).clientDao()

    init {
        viewModelScope.launch {
            user = userDao.getUserForSurname(surname)
        }
    }
}
class MainViewModel(应用程序:应用程序):AndroidViewModel(应用程序){
私人val姓氏=“Doe”
lateinit val客户端:LiveData
私有val userDao:userDao=
MyRoomDatabase.getDatabase(应用程序).clientDao()
初始化{
viewModelScope.launch{
user=userDao.getUserForSurname(姓氏)
}
}
}
更多信息请访问: -

免责声明:没有测试上述解决方案,但它应该会给您一个想法


编辑:理想情况下,LiveData只应在视图模型中使用,因为它们是为此类情况而设计的,不用于观察数据库事务。我建议将Dao替换为Coroutine的流,并使用转换为LiveData。

我建议您看看这个

文件室在返回的实体周围显示不同的包装,例如:

  • RxJava
  • 流协同路由
  • 实时数据
因此,您可以将Dao更改为:

@Query("SELECT * FROM User WHERE surname LIKE :surname")
abstract fun getUserForSurname(surname: String): LiveData<User>
@Query(“从用户中选择*,如:姓氏”)
抽象趣味getUserForSurname(姓氏:String):LiveData
上面的意思是,对用户条目的任何更改都将向LiveData的侦听器发出一个观察结果

视图模型

class MainViewModel(application: Application) : AndroidViewModel(application) {

    private val surname = "Doe"
    lateinit val client: LiveData<User>
    private val userDao: UserDao =
        MyRoomDatabase.getDatabase(application).clientDao()

    init {
        viewModelScope.launch {
            user = userDao.getUserForSurname(surname)
        }
    }
}
class MainViewModel(应用程序:应用程序):AndroidViewModel(应用程序){
私人val姓氏=“Doe”
lateinit val客户端:LiveData
私有val userDao:userDao=
MyRoomDatabase.getDatabase(应用程序).clientDao()
初始化{
viewModelScope.launch{
user=userDao.getUserForSurname(姓氏)
}
}
}
更多信息请访问: -

免责声明:没有测试上述解决方案,但它应该会给您一个想法


编辑:理想情况下,LiveData只应在视图模型中使用,因为它们是为此类情况而设计的,不用于观察数据库事务。我建议将Dao替换为Coroutine的流,并使用转换为LiveData。

将metod返回类型更改为Dao后,我出现了此错误
不确定如何将游标转换为此方法的返回类型
LiveData,因为返回类型仅适用于列表,不是吗?您应该删除suspend。谢谢,它可以工作,也感谢您的编辑提示,它会很有用:)将metod返回类型更改为dao后,我遇到了这个错误
不确定如何将光标转换为此方法的返回类型
LiveData,因为返回类型仅适用于列表,不是吗?您应该删除suspend。谢谢,它可以工作,也感谢您的编辑提示,它将非常有用:)