Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Architecture Components ViewModel - communication with Service/IntentService

I'm exploring Google's Android Architecture Components. In my project I'm relying on Services and IntentServices. What is the correct way to communicate with app's ViewModel from an IntentService or Service? Is it achievable using LiveData?

like image 981
Jan Slominski Avatar asked Oct 11 '17 07:10

Jan Slominski


1 Answers

TL;DR It's achievable - use an observer relationship. Your IntentService and likely location service should not be aware of your ViewModel. Consider using a Repository. LiveData can be used (see postValue). It's good for updating the UI (ViewModel to Activity communication) because it's lifecycle-aware. When you're not updating the UI, you could consider RxJava.


It depends on what architecture you're following. If you're doing something similar to what's described in the Guide to App Architecture, your IntentService is probably started by your remote data source code:

enter image description here

Your remote data source code would have an observable (Rx Flowable, LiveData, etc) which I'll call observable A, for the data downloaded by your intent service. You Repository class (if you use one) would have an observable b and your ViewModel would have an observable c.

The Repository subscribes to the observable in your networking code (observable A), the ViewModel subscribes to the observable in your Repository (observable B), and your Activity/Fragment/View subscribes to the observable in your ViewModel (observable c). Then...

  1. IntentService gets data back and sets observable A
  2. This triggers your Repository because it's subscribed - it does the type of data processing the repository is supposed to do, like saving the data to a database.
  3. When your repository is done, it sets observable B with the newly processed data.
  4. This triggers your ViewModel because it's subscribed - it does the type of data processing ViewModels do, namely formatting the data so that it's ready for the view, then sets observable C...
  5. This triggers your Activity/Fragment/View which updates the UI

It's basically a long chain of observer relationships all the way up. At each level, the appropriate processing is done, then it sets an observable, which triggers the next level with the new data. This allows you to avoid strong coupling with your IntentService/Repository/ViewModel.

Your Services would not be aware of your ViewModel (or Repository if you have one), they should simply set the value of an observable. If you want to skip having a repository, you could have the ViewModel observe your remote data source class, but if you need to do any logic like saving the data you downloaded to a database, you probably want a Repository.

Two notes about LiveData - If you need to update LiveData when you're doing a background operation, use postValue.

LiveData is lifecycle-aware, which makes it particularly well suited for observation by things with lifecycles (Activities/Fragments). The observe method takes a LifecycleOwner.

For observers like B and A in your Repository/Networking code, there likely won't be a LifecycleOwner. This means either doing something like using observerForever, or using another observable, like an RxFlowable.

like image 88
Lyla Avatar answered Nov 11 '22 08:11

Lyla