i am storing user information in a local room database. In activities and fragments I use AndroidViewModel and LiveData to listen to changes made to the database and update the UI.
Now I want to analyze all of the past user data to give recommendations for future decisions. My recommendations change on every change to the database made by the user so I need to update my reommendations frequently while doing the same calculations over and over again.
I was thinking about starting a service on app start that listens to database changes via ViewModel and LiveData and updates my recommendations (which are also stored in the same database). But somehow a Service cannot
viewModel = ViewModelProviders.of(this).get(DataViewModel.class);
Basically I simply need to read all entries from the database, analyze the data and update 5-10 values every time the database content changes.
How and where should I do my calculations if not in a service? Maybe I am trapped in a wrong thought and a service is not the right way to do it so any idea on how to do this is very much appreciated!
Room autogenerates implementations of your @Database and @Dao annotated classes the first time you compile your code after creating a Room Database. The implementation of UserDatabase and UserDao in the preceding example is generated automatically by the Room annotation processor.
Room provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite. In case of SQLite, There is no compile time verification of raw SQLite queries. But in Room there is SQL validation at compile time.
Room is a Database Object Mapping library that makes it easy to access database on Android applications. Rather than hiding the detail of SQLite, Room tries to embrace them by providing convenient APIs to query the database and also verify such queries at compile time.
I ended up using a Service and solved my problem as follows:
In the onCreate
method of my Application object
I bind MyService
to it:
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder iBinder) {
service = ((MyService.MyLocalBinder) iBinder ).getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
Intent intent = new Intent(this, MyService.class);
getApplicationContext().bindService(intent, serviceConnection, BIND_AUTO_CREATE);
Binding a Service to the application context should keep the Service alive as long as the application is not destroyed. In MyService
I get an instance of ViewModel via AndroidViewModelFactory
like this
MyViewModel myViewModel = ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication()).create(MyViewModel.class);
and I am able to observe the fetched LiveData from the ViewModel via observeForever
like this
Observer<List<Entry>> obsEntries = new Observer<List<Entry>>() {
@Override
public void onChanged(@Nullable List<Entry> entries) {
//perform calculations with entries in here
}
};
viewModel.getEntries().observeForever(obsEntries);
Important: Remove the observer from the LiveData reference in onDestroy
of the Service (that is why I keep a local reference to the Observer object):
@Override
public void onDestroy() {
super.onDestroy();
viewModel.getEntries().removeObserver(obsEntries);
}
Thanks everybody!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With