In my application I want use MVI for application architecture and I should use Room database.
I have one activity
and one fragment
!
In fragment I receive data from user and save into database and in activity show this data into recyclerview.
I write below codes and my data successfully save into database!
But for show it into activity, I should exit from application and enter to show data list!
I want without exit from application, update automatically this list.
Dao codes :
@Query("SELECT * FROM my_table")
fun getAllData(): MutableList<Entity>
Repository codes:
class MyRepository @Inject constructor(private val dao: DataDao) {
fun allData() = dao.getAllData()
}
ViewModel codes:
@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())
}
}
}
Activity codes :
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
}
}
}
}
}
How can I fix this problem?
CodePudding user response:
Several methods below can solve this problem.
- Use EventBus. Send an EventBus message after saving data to database in fragment and handle this message in
MyViewModel
or your Activity to reload data - In your 'dao' interface, change function return type to
LiveData
:fun getAllData(): LiveData<MutableList<Entity>>
. When related data changed in database, Room database automaticly notify changes toObservers
. Check this - Use
Broadcast
like usingEventBus
- If fragment is contained in the
Activity
which requires the notification when data changed, useSharedViewModel
to notify activity.
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()
}
}