В моем приложении я хочу использовать MVI для архитектуры приложения, и я должен использовать базу данных Room.
У меня есть один activity и один fragment!
Во фрагменте я получаю данные от пользователя и сохраняю в базу данных, а в действии показываю эти данные в recyclerview.
Я пишу ниже коды, и мои данные успешно сохраняются в базе данных!
Но чтобы показать это в действии, я должен выйти из приложения и войти, чтобы показать список данных!
Я хочу, не выходя из приложения, автоматически обновлять этот список.
Коды Дао:
@Query("SELECT * FROM my_table")
fun getAllData(): MutableList<Entity>
Коды репозитория:
class MyRepository @Inject constructor(private val dao: DataDao) {
fun allData() = dao.getAllData()
}
Коды ViewModel:
@HiltViewModel
class MyViewModel @Inject constructor(private val repository: MyRepository) : ViewModel() {
val mainIntent = Channel<MainIntent>()
private val _state = MutableStateFlow<MainState>(MainState.Idle)
val state : StateFlow<MainState> get() = _state
init {
handleIntent()
}
private fun handleIntent() {
viewModelScope.launch {
mainIntent.consumeAsFlow().collect{
when(it){
is MainIntent.LoadAllData-> fetchingAllDataList()
}
}
}
}
private fun fetchingAllDataList() {
viewModelScope.launch {
_state.value = MainState.LoadData(repository.allData())
}
}
}
Коды активности:
lifecycleScope.launch {
//Send
viewModel.mainIntent.send(MainIntent.LoadAllData)
//Get
viewModel.state.collect { state ->
when (state) {
is MainState.Idle -> {}
is MainState.LoadData -> {
dataAdapter.setData(state.list)
fataList.apply {
layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
adapter = noteAdapter
}
}
}
}
}
Как я могу решить эту проблему?
Несколько методов ниже могут решить эту проблему.
MyViewModel или в своем действии для перезагрузки данных.LiveData: fun getAllData(): LiveData<MutableList<Entity>>. Когда связанные данные изменяются в базе данных, база данных Room автоматически уведомляет об изменениях в Observers. Проверьте этоEventBusActivity содержится фрагмент, который требует уведомления при изменении данных, используйте SharedViewModel для уведомления об активности.class MyFragment: BottomDialogSheetFragment {
var entityChangeListener: IEntityChangeListener? = null
...
// after saving data to database
entityChangeListener?.onChanged()
}
class MyActivity {
fun showDialog() {
val fragment = MyFragment()
fragment.entityChangeListener = object : IEntityChangeListener {
override fun onChanged() {
// change [fetchAllDataList] function to public
myViewModel.fetchAllDataList()
}
}
}
}
interface IEntityChangeListener {
fun onChanged()
}
// using SharedViewModel
class MyFragment: BottomDialogSheetFragment {
var entityViewModel by sharedViewModel<EntityViewModel>
...
// saving entity data
entityViewModel.saveData(entities)
}
class MyActivity {
// shared view model for entity database business
val entityViewModel by viewModels<EntityViewModel>
// viewmodel for other business logic
val viewModel by viewModels<MyViewModel>
}
class EntityViewModel: ViewModel(){
...
private val _state = MutableStateFlow<MainState>(MainState.Idle)
val state : StateFlow<MainState> get() = _state
fun fetchingAllDataList() {
viewModelScope.launch(Dispatchers.IO) {
_state.value = MainState.LoadData(repository.allData())
}
}
fun saveData(entities: List<Entity>) {
dao.save(entities)
fetchingAllDataList()
}
}
@Dr.KeyOk Если вы показываете фрагмент в действии, вы можете просто добавить параметр ChangedListener во фрагмент, чтобы уведомить о перезагрузке активности. Смотрите ответ выше, я добавлю привязку к коду, чтобы показать, как использовать этот способ
Как я могу автоматически обновлять список только с помощью StateFlow?
@Dr.KeyOk Я обновил свой ответ, вы можете проверить его.
Спасибо, мой друг. Не могли бы вы помочь мне с методом 4? Для показа фрагмента я использовал BottomDialogSheetFragment. В действии у меня есть кнопка, и при нажатии на эту кнопку отображается мой фрагмент. Я знаю, что если бы я использовал EventBus или LiveData, моя проблема была бы исправлена! но я не хочу использовать это. Вы можете помочь мне с SharedViewModel? пожалуйста