Android MVP pattern package structure

前端 未结 3 1693
一整个雨季
一整个雨季 2020-12-16 00:11

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

相关标签:
3条回答
  • 2020-12-16 00:43

    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

    0 讨论(0)
  • 2020-12-16 00:53

    The good practice is to separate stuffs by feature (sometimes considered as module) and layer, not by their role. Reason: class/interface name already told that, e.g LoginView, LoginPresenter, LoginFragment, LoginActivity etc.

    0 讨论(0)
  • 2020-12-16 00:54

    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.

    0 讨论(0)
提交回复
热议问题