首页 > 解决方案 > 观察从后台线程进行的数据库对象更改

问题描述

我遇到了在我的应用程序中观察数据的问题。

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

@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

在活动 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)
        }
    }
}

该特定用户的名称在后台线程中更改。当我检查 db 本身的值时,名称确实不同。重新启动活动后,文本视图也发生了变化。换句话说:db 值改变了,但观察者永远不会被调用。我知道我在 viewmodel 的 init 方法中只要求一次该值,这可能是一个问题。是否可以在不重新启动活动的情况下查看实际更改?

标签: androidandroid-room

解决方案


我建议你看看这个Codelab

Room 在返回的实体周围暴露了不同的包装器,例如:

  • RxJava
  • 流协程
  • 实时数据

所以你可以这样改变你的道:

@Query("SELECT * FROM User WHERE surname LIKE :surname")
abstract fun getUserForSurname(surname: String): LiveData<User>

以上意味着对用户条目的任何更改都会向 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)
        }
    }
}

阅读更多: - https://developer.android.com/training/data-storage/room/index.html

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

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


推荐阅读