Как обновить базу данных Room в Android

В моем приложении я хочу использовать 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
                }
            }
        }
    }
}

Как я могу решить эту проблему?

0
0
80
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Несколько методов ниже могут решить эту проблему.

  1. Используйте EventBus. Отправьте сообщение EventBus после сохранения данных в базе данных во фрагменте и обработайте это сообщение в MyViewModel или в своем действии для перезагрузки данных.
  2. В вашем интерфейсе «дао» измените тип возвращаемого значения функции на LiveData: fun getAllData(): LiveData<MutableList<Entity>>. Когда связанные данные изменяются в базе данных, база данных Room автоматически уведомляет об изменениях в Observers. Проверьте это
  3. Используйте Трансляция, как при использовании EventBus
  4. Если в Activity содержится фрагмент, который требует уведомления при изменении данных, используйте 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()
    }
}

Спасибо, мой друг. Не могли бы вы помочь мне с методом 4? Для показа фрагмента я использовал BottomDialogSheetFragment. В действии у меня есть кнопка, и при нажатии на эту кнопку отображается мой фрагмент. Я знаю, что если бы я использовал EventBus или LiveData, моя проблема была бы исправлена! но я не хочу использовать это. Вы можете помочь мне с SharedViewModel? пожалуйста

Dr.KeyOk 30.09.2022 13:02

@Dr.KeyOk Если вы показываете фрагмент в действии, вы можете просто добавить параметр ChangedListener во фрагмент, чтобы уведомить о перезагрузке активности. Смотрите ответ выше, я добавлю привязку к коду, чтобы показать, как использовать этот способ

leimenghao 30.09.2022 13:15

Как я могу автоматически обновлять список только с помощью StateFlow?

Dr.KeyOk 30.09.2022 13:25

@Dr.KeyOk Я обновил свой ответ, вы можете проверить его.

leimenghao 30.09.2022 13:31

Другие вопросы по теме