AndroidPub
Published in

AndroidPub

Android Bound Services and MVP

Recently while working on a hobby project of mine, an XMPP chat client, I faced an issue fitting an Android Bound Service into MVP design pattern. The service took user input, processed it and finally passed the result to the Activity to be shown to the user. The project was implemented using MVP design pattern with Dagger2.

Due to the nature of Bound Services, being an Android component that is tightly coupled with the Activity, my main goal was to stick to MVP as much as possible and communicate with the service via the presenter. I couldn’t find any article that touched bound services in the context of MVP so I decided to share my own experience.

More Lifecycle Callbacks

Bound Services add extra lifecycle callbacks to the Activity via the ServiceConnection interface that must be registered when binding the service to the Activity. This meant that I could only get the service instance when ServiceConnection#onServiceConnected() was called. It became clear to me that Dagger isn’t going to fit here due to the presenter being injected with its dependencies when the Activity was created.

Attach — Detach

As Dagger was not an option, it meant I had to pass the service instance to the presenter whenever the service was connected. I already had attach() and detach() methods in place so I decided to pass the service instance with attach() when the service was connected and clear the reference in detach() when it was disconnected. Instead of calling attach()/detach() in onStart()/onStop() respectively, I simply moved the calls to onServiceConnected()/onServiceDisconnected() and replaced attach()/detach() calls with bindService()/unbindService().

I wanted to maintain the presenter’s testability so that I could run the tests locally without Android framework dependency. Just like any other presenter dependency, the bound service was no different. I simply abstracted away the service implementation by creating a service interface and made the presenter work against that. This way, I could easily mock the service in the presenter’s unit tests.

This solution worked very nicely. The only downside which I found so far is the necessity to do null checks before every service call.

Android Bound Service with MVP

In the code above, you can see that when ChatService is bound, it returns LocalBinder instance which has getService() method that returns the service interface. The actual service implementation is implemented in another class and is injected to ChatService#onCreate() using Dagger. This way, you can unit test the service implementation in isolation — independently from the Service lifecycle. MessagingService and MainPresenter implementations were left for brevity.

I’d be really interested to hear how others have handled Bound Services with MVP so please leave your feedback in the comments section below.

Sample App

Here’s a sample messaging app that I made which utilizes this pattern.

Further reading
If you’re looking for more info about Android MVP, I highly recommend this comprehensive article by Francesco Cervone.

https://twitter.com/nimroddayan

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store