我正在做一个练习项目,我将订阅者存储在房间数据库中。我在 DAO 中使用流,稍后在视图模型中将它们作为状态流。这很好用,但是当我更新任何订阅者(更改他们的姓名或电子邮件)时,用户界面为什么没有反应。它仅在我插入或删除时更新。可能是什么问题呢?以这种方式使用 StateFlow 是否最佳?
(它适用于 LiveData,但我想尝试使用 StateFlows)
我感谢任何形式的帮助
视图模型:
class SubscriberViewModel(private val repository: SubscriberRepository) : ViewModel() {
private var isUpdateOrDelete = false
private lateinit var subscriberToUpdateOrDelete: Subscriber
val inputName = MutableStateFlow("")
val inputEmail = MutableStateFlow("")
private val _isDataAvailable = MutableStateFlow(false)
val isDataAvailable : StateFlow<Boolean>
get() = _isDataAvailable
val saveOrUpdateButtonText = MutableStateFlow("Save")
val deleteOrDeleteAllButtonText = MutableStateFlow("Delete all")
private val _subscribers : MutableStateFlow<List<Subscriber>> = MutableStateFlow(emptyList())
get() {
viewModelScope.launch(Dispatchers.IO) {
repository.subscribers.collect {
field.value = it
}
}
return field
}
val subscribers : StateFlow<List<Subscriber>>
get() = _subscribers
private fun clearInput() {
inputName.value = ""
inputEmail.value = ""
isUpdateOrDelete = false
saveOrUpdateButtonText.value = "Save"
deleteOrDeleteAllButtonText.value = "Delete all"
}
fun initUpdateAndDelete(subscriber: Subscriber) {
inputName.value = subscriber.name
inputEmail.value = subscriber.email
isUpdateOrDelete = true
subscriberToUpdateOrDelete = subscriber
saveOrUpdateButtonText.value = "Update"
deleteOrDeleteAllButtonText.value = "Delete"
}
fun saveOrUpdate() {
if (isUpdateOrDelete) {
subscriberToUpdateOrDelete.name = inputName.value
subscriberToUpdateOrDelete.email = inputEmail.value
update(subscriberToUpdateOrDelete)
} else {
val name = inputName.value
val email = inputEmail.value
if (name.isNotBlank() && email.isNotBlank()) {
insert(Subscriber(0, name, email))
}
inputName.value = ""
inputEmail.value = ""
}
}
fun deleteOrDeleteAll() {
if (isUpdateOrDelete) {
delete(subscriberToUpdateOrDelete)
} else {
deleteAll()
}
}
private fun insert(subscriber: Subscriber) = viewModelScope.launch(Dispatchers.IO) {
repository.insert(subscriber)
//StateFlow changed, UI received the change
_isDataAvailable.value = true
}
private fun update(subscriber: Subscriber) = viewModelScope.launch(Dispatchers.IO) {
repository.update(subscriber)
//StateFlow changed, UI can't receive the change
clearInput()
}
private fun delete(subscriber: Subscriber) = viewModelScope.launch(Dispatchers.IO) {
repository.delete(subscriber)
//StateFlow changed, UI received the change
clearInput()
}
private fun deleteAll() = viewModelScope.launch(Dispatchers.IO) {
repository.deleteAll()
//StateFlow changed, UI received the change
_isDataAvailable.value = false
}
}
主要活动:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: SubscriberViewModel
private lateinit var viewModelFactory: SubscriberViewModelFactory
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
val dao = SubscriberDatabase.getInstance(application).subscriberDAO
viewModelFactory = SubscriberViewModelFactory(SubscriberRepository(dao))
viewModel = ViewModelProvider(this, viewModelFactory)[SubscriberViewModel::class.java]
binding.viewModel = viewModel
binding.lifecycleOwner = this
initRecycleView()
}
private fun initRecycleView() {
binding.recyclerViewSubscribers.layoutManager = LinearLayoutManager(
this@MainActivity,
LinearLayoutManager.VERTICAL, false
)
displaySubscribersList()
}
private fun displaySubscribersList() {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.subscribers.collect { list -> //This code doesn't run when I update a subscriber
binding.recyclerViewSubscribers.adapter = SubscriberRecyclerViewAdapter(list) {
subscriber: Subscriber -> listItemClicked(subscriber)
}
}
}
}
}
private fun listItemClicked(subscriber: Subscriber) {
Toast.makeText(this, "${subscriber.name} is selected", Toast.LENGTH_SHORT).show()
viewModel.initUpdateAndDelete(subscriber)
}
}