I am trying to implement MVP architecture using google sample code for mvp. I have an activity as View that has a presenter and model. On button click user can capture and save image in external storage. And on capture click, I also need to play a sound.
I am not sure which code should be put in which class because I cannot put camera capture and play sound code in Activity (which I treat as view) to keep the view as dumb as possible and I cannot put that code in Presenter because it uses Android framework classes (context etc).
So, the only option is to put it in model but in sample code, model only has Repositories (that I believe is relevant to data sources only local/remote).
How to put this code in model and how to link it with other components like View and Presenter? Any guidelines?
Here's one way you can go about solving an issue like that.
Your problem is that some code makes sense to go into a presenter, however it's too Android
y, so you can simply interface
around it.
What you basically need is two things that can do certain functions.
interface CapturingSoundPlayer {
void playSound();
}
interface ImageCapturer {
void captureImage();
}
Please note that names and method signatures are up to you and what you need, I am merely using them to make a point.
Now it's perfectly safe for your application to have those two interfaces as dependencies, they have nothing to do with Android, we have simply take then technology out of the equation and only left the behaviour.
You need to pass these dependencies to your presenter and use them whenever needed.
class Presenter {
private final CapturingSoundPlayer soundPlayer;
private final ImageCapturer capturer;
Presenter(CapturingSoundPlayer soundPlayer, ImageCapturer capturer) {
this.soundPlayer = soundPlayer;
this.capturer = capturer;
}
void onCaptureButtonClicked() {
soundPlayer.playSound();
capturer.captureImage();
}
}
Now the implementation for those interfaces can be completely separate from your Activity, making your view still stupid.
Those interfaces (and their implementation) are simply logical units/entities that your presenter uses to split up the logic. I simply think of the functions of "capture" and "playSound" as simple actions, just like view.showLoading
, and your presenter plays an orchestrator, it uses "something" to manipulate the view, which is the view interface, and it uses something else to manipulate sound, which is the interface for doing that.
if repositories are considered to be data sources, then in my opinion those helpers don't fit under that definition.
If you have a utility to retrieve the images that has been captured, that would basically can be considered as a repo for your images, but simply taking an image, is just another action.
You can structure/organise them as you feel fit, but just because you are using MVP, not every class you create has to be either one of those letters (M/V/P).
Sometimes any of those layers will need classes that logical units to do something, so that you have better separation of concerns.
Consider you have quite complex formatting logic, it would make sense to separate that in a separate class other than the presenter, but does that mean that the separate class is now model? It could, but it doesn't have to be.