Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read data and listen to changes from Room database in a Service?

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

  1. get a ViewModel via viewModel = ViewModelProviders.of(this).get(DataViewModel.class);
  2. observe a LiveData object as it is not a LifecycleOwner.

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!

like image 292
steasy Avatar asked Jun 18 '18 18:06

steasy


People also ask

How does Room database work?

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.

What is the difference between SQLite and Room database?

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.

Which element is Room database responsible for query?

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.


1 Answers

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!

like image 142
steasy Avatar answered Oct 15 '22 00:10

steasy