To preface, I already have a fragment which observes the LiveData in the same way as below, and it works perfectly. For some reason, when trying to use the service as lifecycle owner I think this is causing a problem, and the observer is not being called.
I have checked the answer here but as I am using the same instance of ViewModel/Dao this shouldn't be my problem. (I think? Correct me if I'm wrong please.)
I have a service which extends HoverMenuService from MattCarroll's Hover. These services display overlay UI's, so I wanted to observe some LiveData from the service to update this UI. I made my service implement LifecycleOwner and basically copied LifecycleService implementation from the source code, so I could use the service as the lifecycle owner and add Observers to the LiveData.
Here's my service
class MyHoverMenuService : HoverMenuService(), LifecycleOwner {
val TAG = "MyHoverMenuService"
val mDispatcher = ServiceLifecycleDispatcher(this)
override fun onHoverMenuLaunched(intent: Intent, hoverView: HoverView) {
Timber.i("onHoverMenuLaunched called.")
val menu: HoverMenu = MyHoverMenu(this, application, ContextThemeWrapper(this, R.style.AppTheme))
hoverView.setMenu(menu)
hoverView.collapse()
}
@CallSuper
override fun onCreate() {
mDispatcher.onServicePreSuperOnCreate()
super.onCreate()
}
@CallSuper
override fun onBind(intent: Intent?): IBinder? {
mDispatcher.onServicePreSuperOnBind()
return super.onBind(intent)
}
@CallSuper
override fun onStart(intent: Intent?, startId: Int) {
mDispatcher.onServicePreSuperOnStart()
super.onStart(intent, startId)
}
@CallSuper
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
}
@CallSuper
override fun onDestroy() {
mDispatcher.onServicePreSuperOnDestroy()
super.onDestroy()
}
@CallSuper
override fun getLifecycle(): Lifecycle {
return mDispatcher.lifecycle
}
}
MyHoverMenu displays 2 Sections, but essentially the ownerService
variable is passed through to this HoverDictionaryScreen class, where the UI is shown.
My HoverDictionaryScreen
class HoverDictionaryScreen(
private val ownerService: MyHoverMenuService
, val application:Application
, val context: Context
) : Content {
private val applicationContext: Context = context.applicationContext
lateinit var dictViewModel: DictionaryInterfaceViewModel
...
fun createScreenView(): View {
val container: ViewGroup = FrameLayout(ContextThemeWrapper(applicationContext, R.style.AppTheme))
binding = DataBindingUtil.inflate(
LayoutInflater.from(applicationContext),
R.layout.fragment_dictionary_interface,
container,
false
)
dictViewModel = ViewModelProvider
.AndroidViewModelFactory.getInstance(application)
.create(DictionaryInterfaceViewModel::class.java)
dictViewModel.totalEntries.observe(ownerService, Observer { totalEntries ->
binding.numberOfEntries.text = "Total number of entries in database : $totalEntries"
})
...
In my DictionaryInterfaceViewModel the totalEntries var is initialised from the dao. So essentially the observer should be called as soon as it is applied (Which does happen in my fragment).
When I check the binding.numberOfEntries isn't updated, and I also checked that the observer isn't called with a log statement.