I have a repository which holds the LiveData object and is used by both activity and a foreground service through a ViewModel. When I start observing from the activity everything works as expected. However observing from the service doesn't trigger the Observe. This is the code I use
class MyService: LifecycleService() { lateinit var viewModel: PlayerServiceViewModel override fun onCreate() { viewModel = MyViewModel(applicationContext as Application) } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { viewModel.getLiveData().observe(this, Observer { data -> // Do something with the data }) } }
Any ideas why it doesn't work and I don't receive the data?
Attach the Observer object to the LiveData object using the observe() method. The observe() method takes a LifecycleOwner object. This subscribes the Observer object to the LiveData object so that it is notified of changes. You usually attach the Observer object in a UI controller, such as an activity or fragment.
[...] However ViewModel objects must never observe changes to lifecycle-aware observables, such as LiveData objects.
liveData declared as val can't change, but you can always update the value of LiveData because it is MutableLiveData . Any change in value of liveData notifies all of its active observers. LiveData is always observed inside a UI Lifecycle owner, which can be an Activity or a Fragment.
With LiveData, this communication is safer: the data will only be received by the View if it's active, thanks to its lifecycle awareness. The advantage, in short, is that you don't need to manually cancel subscriptions between View and ViewModel.
I used ViewModel
with LiveData
in LifecycleActivity
and Fragments
it works and observes data as expected.
Coming to your problem, when you create new ViewModel
from Service
or any another Activity
it creates new instance of all the LiveData and other dependencies required for ViewModel
to query from Repository and ultimately DAO. If you are not using the same DAO for both ViewModels your LiveData
may not update as it is observing on different instance of DAO.
I used Dagger2
in my project to maintain Singleton instances for DAO and other common dependencies. So you can try making your Repository and DAO singleton to keep it consistent across the Application.
I tried it using with Services
with LifecycleService
with same flow and it worked for me.
I got following output when data changed form null to pulled data
D/ForegroundService: onStartCommand: Resource{status=LOADING, message='null', data=null} D/ForegroundService: onStartCommand: Resource{status=SUCCESS, message='null', data=TVShow(id=14,...
At first it showed null data as data wasn't present in database After pulling data from network and updating into database Observer
observed data automatically.
Worked out using following code
public class ForegroundService extends LifecycleService { private static final String TAG = "ForegroundService"; private TVShowViewModel tvShowViewModel; private TVShow tvShow; @Inject TVShowDataRepo tvShowDataRepo; @Override public void onCreate() { super.onCreate(); AndroidInjection.inject(this); tvShowViewModel = new TVShowViewModel(tvShowDataRepo); tvShowViewModel.init(14); } @Override public int onStartCommand(Intent intent, int flags, int startId) { tvShowViewModel.getTVShow().observe(this, tvShowResource -> { Log.d(TAG, "onStartCommand: " + tvShowResource); }); return super.onStartCommand(intent, flags, startId); } }
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