Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difficulties implementing Model-View-Presenter in Android

Model-View-Presenter (MVP) is a well known design pattern for GUI applications. For Android, implementing the business logic in a plain Java module facilitates testing without requiring an Android emulator.

However, I am having difficulties implementing the pattern on Android because of special requirements to the GUI of Android applications:

  • An Activity may be destroyed at any point (incoming call, user presses home button, ...), and when recreated it should be in the exact same state as when it was left. This is unlike most other GUI applications.

  • An Activity can go through many lifecycle states. It may be paused in which case the UI of the Activity should not be modified. If for example some data is being loaded in the background, it cannot be delivered to the View part of MVP (Activity) if it is in a paused state. Again, this is an unusual requirement.

I have read the blog post MVP for Android and looked at the example source code. The end goal I am trying to achieve by using the MVP pattern is to be able to translate all business logic to Objective-C using the transpiler j2objc, such that the business logic can be reused while implementing the same app on iOS.

Is there anyone that have implemented the MVP pattern for Android successfully, and in that case, what am I missing?

like image 515
foens Avatar asked Jul 11 '14 12:07

foens


2 Answers

I suggest implementing the MVP component without involving Activity, perhaps conceptually thinking about what would be useful on both Android and GWT. Create the component using test-driven-development with a mocked View interface, adding tests until the business logic is fully implemented and verified. TDD helps keep the component's API lean (why write tests for stuff you don't need?), which makes porting the component easier.

The Activity requirements you describe can be generalized to be platform-independent: the component should be serializable (small 's', not specifically Java serialization), and needs to accept lifecycle state events. Those, too, can be fully tested using mocks for system features. As you go through this step, you'll likely notice that few of the Activity requirements are necessarily Android-specific, and may be useful on other platforms. Avoid creating huge service APIs; to support serialization, for example, all that's needed are store/load methods, not something like the Parcel API. I've found describing such service APIs to another developer on a whiteboard to be a great way to find unnecessary fluff.

Next, port the component to Android, perhaps by creating an Activity that delegates to the component and provides Android-specific implementation classes for the mocked interfaces. It should all "just work" the first time, but in reality, some requirements may have been missed, so add them to the platform-independent part and repeat.

When you're ready to port to iOS, reimplement those previously mocked interfaces. If these interfaces are lean, it will probably be easier to create them directly in Objective-C, importing the protocol headers generated by j2objc. For example, j2objc's NSDictionaryMap class implements java.util.Map with an NSDictionary implementation -- no need to write and translate a Java version since its just using iOS APIs.

like image 154
tball Avatar answered Sep 17 '22 20:09

tball


I find that the MVP variant Android is built around is a step in the right direction for isolating the business logic in a app. However, if you want to achieve a better separation of concerns, and as a result more reusable domain/business logic, I recommend using the Presenter First pattern (which you briefly mention yourself in the comment). Aside from decreasing coupling it lends itself well to TDD and allows you to unit test all your business logic.

I recently started a GitHub repo with Presenter First examples for Android. Due to the complexity of the Android architecture it's not straightforward to implement the pattern The views tend to be "fatter" than what seems to be acceptable in a normal Presenter First app, mostly because of the activity lifecycle and other oddities as you mention yourself. I've done my best to decouple the business logic from the platform but there's definitely room for improvement. You can find the examples at:

http://github.com/olerass/presenter-first-android

Maybe you can use some ideas from there? Or even better contribute some of your own.

like image 29
olerass Avatar answered Sep 19 '22 20:09

olerass