Home > Software engineering >  How to update Room database in Android
How to update Room database in Android

Time:09-30

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.

  1. 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
  2. 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 to Observers. Check this
  3. Use Broadcast like using EventBus
  4. If fragment is contained in the Activity which requires the notification when data changed, use SharedViewModel 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()
    }
}
  • Related