I saw various great tutorials on MVP pattern in android, but the authors all seem to have different practice on packaging.
The first tutorial I saw did the packaging by functionalities. Such as, "Login", "Join", "UI" package.
The UI package has only activities, the "Login" package has the interfaces for the presenter and the concrete presenter, and this package contains a sub package "Model" that contains everything about the login model(communications with the server). The "Join" package has the same composition as the "Login" package.
But the other one I saw did the packaging by scene, such as "Join", "Login".
"Join" package contains an activity, and three sub packages named "Model", "View", "Presenter".
What is the best practice? Are there any articles that handles this issue?
MVP (Model — View — Presenter) architecture is one of the most popular architecture patterns and is valid in organizing the project. MVP (Model — View — Presenter) comes into the picture as an alternative to the traditional MVC (Model — View — Controller) architecture pattern.
Model View Presenter (MVP) The MVP pattern is similar to the MVC pattern. It is derived from MVC pattern, wherein the controller is replaced by the presenter. This pattern divides an application into three major aspects: Model, View, and Presenter.
MVP: This software architecture has a dependent user interface as it uses the presenter to act as a link between the view and the model. MVVM: MVVM implements data binding and allows easy separation of the model and the view.
MVP is a user interface architectural pattern engineered to facilitate automated unit testing and improve the separation of concerns in presentation logic: The model is an interface defining the data to be displayed or otherwise acted upon in the user interface.
App should have package according to
features
not by the common functionality.
I find people make activity, fragments, Adapters,etc. common purpose package in one group but this is bad practice!
Mostly developers group them like this because they do this to keep the same package structure for all the applications they work on. But that is very wrong decision cause it is always hard to find classes when they are grouped only because they share same parent classes!
We should group the classes according to parent classes but only if we are making some API but if we are making a custom product for our client then it is very bad practice.!
Like all activities most developers put in activity package because all activity classes extends the Activity class.That makes sense that this is only activity related package but it is hard to go through those packages.
Suppose we have One OrderListActivity class and we fetch the order list from server and then display it in one OrderListFragment class and obviously for that we need OrderListAdapter to show the order listing. so when customer ask for some modification or any feature he wants on that Order List screen we have to go to many packages to satisfy client need. Like we have to go to activity package and modify some thing in OrderListActivity and then go to OrderListFragment and then OrderListAdapter and then OrderListViewHolder,etc.!So This becomes too hard and we may create issues in process of modifying!
so we should group together the classes which are getting changed/modify together.
That's the best practice and so we should group all those classes who are responsible for OrderListing feature in one package and we call it orderdlist package.
Please check my this medium post i have explained the package structure too in that:--
https://medium.com/@kailash09dabhi/mvp-with-better-naming-of-implementation-classes-dry-principle-e8b6130bbd02
I just repost my answer here
I often put business logic code in Model Layer (don't make confusion with model in database). I often rename as XManager
for avoiding confusion (such as ProductManager
, MediaManager
...) so presenter class just uses for keeping workflow.
The rule of thumb is no or at least limit import android package in presenter class. This best practice supports you easier in testing presenter class because presenter now is just a plain java class, so we don't need android framework for testing those things.
For example here is my mvp workflow.
View class: This is a place you store all your view such as button, textview ... and you set all listeners for those view components on this layer. Also on this View, you define a Listener class for presenter implements later. Your view components will call methods on this listener class.
class ViewImpl implements View {
Button playButton;
ViewListener listener;
public ViewImpl(ViewListener listener) {
// find all view
this.listener = listener;
playButton.setOnClickListener(new View.OnClickListener() {
listener.playSong();
});
}
public interface ViewListener {
playSong();
}
}
Presenter class: This is where you store view and model inside for calling later. Also presenter class will implement ViewListener interface has defined above. Main point of presenter is control logic workflow.
class PresenterImpl extends Presenter implements ViewListener {
private View view;
private MediaManager mediaManager;
public PresenterImpl(View, MediaManager manager) {
this.view = view;
this.manager = manager;
}
@Override
public void playSong() {
mediaManager.playMedia();
}
}
Manager class: Here is the core business logic code. Maybe one presenter will have many managers (depend on how complicate the view is). Often we get Context
class through some injection framework such as Dagger
.
Class MediaManagerImpl extends MediaManager {
// using Dagger for injection context if you want
@Inject
private Context context;
private MediaPlayer mediaPlayer;
// dagger solution
public MediaPlayerManagerImpl() {
this.mediaPlayer = new MediaPlayer(context);
}
// no dagger solution
public MediaPlayerManagerImpl(Context context) {
this.context = context;
this.mediaPlayer = new MediaPlayer(context);
}
public void playMedia() {
mediaPlayer.play();
}
public void stopMedia() {
mediaPlayer.stop();
}
}
Finally: Put those thing together in Activities, Fragments ... Here is the place you initialize view, manager and assign all to presenter.
public class MyActivity extends Activity {
Presenter presenter;
@Override
public void onCreate() {
super.onCreate();
IView view = new ViewImpl();
MediaManager manager = new MediaManagerImpl(this.getApplicationContext());
// or this. if you use Dagger
MediaManager manager = new MediaManagerImpl();
presenter = new PresenterImpl(view, manager);
}
@Override
public void onStop() {
super.onStop();
presenter.onStop();
}
}
You see that each presenter, model, view is wrapped by one interface. Those components will called through interface. This design will make your code more robust and easier for modifying later.
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