简体   繁体   English

Android MVP模式包结构

[英]Android MVP pattern package structure

I saw various great tutorials on MVP pattern in android, but the authors all seem to have different practice on packaging. 我在android中看到了关于MVP模式的各种精彩教程,但作者们似乎都在包装上有不同的练习。

The first tutorial I saw did the packaging by functionalities. 我看到的第一个教程按功能进行了打包。 Such as, "Login", "Join", "UI" package. 如,“登录”,“加入”,“UI”包。

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). UI包只有活动,“Login”包具有演示者和具体演示者的接口,并且该包包含一个子包“Model”,其中包含有关登录模型的所有内容(与服务器的通信)。 The "Join" package has the same composition as the "Login" package. “Join”包与“Login”包具有相同的组成。

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". “Join”包中包含一个活动,以及三个名为“Model”,“View”,“Presenter”的子包。

What is the best practice? 什么是最佳做法? Are there any articles that handles this issue? 有没有处理这个问题的文章?

App should have package according to features not by the common functionality. 应用程序应根据features而不是通用功能进行打包。

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.! 我们应该根据父类对这些类进行分组,但只有在我们制作一些API但是如果我们为我们的客户制作定制产品时,这是非常糟糕的做法。

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. 像大多数开发人员放入活动包的所有活动一样,因为所有活动类都扩展了Activity类。这是有意义的,这只是与活动相关的包,但很难通过这些包。

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. 假设我们有一个OrderListActivity类,我们从服务器获取订单列表,然后在一个OrderListFragment类中显示它,显然我们需要OrderListAdapter来显示订单列表。 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! 就像我们必须转到活动包并在OrderListActivity中修改一些东西然后转到OrderListFragment然后转到OrderListAdapter然后转到OrderListViewHolder等等!所以这变得太难了我们可能会在修改过程中产生问题!

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. 这是最佳实践,因此我们应该将所有负责OrderListing功能的类分组到一个包中,我们称之为orderdlist包。

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 https://medium.com/@kailash09dabhi/mvp-with-better-naming-of-implementation-classes-dry-principle-e8b6130bbd02

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, eg LoginView, LoginPresenter, LoginFragment, LoginActivity etc. 原因:类/接口名称已经告知,例如LoginView,LoginPresenter,LoginFragment,LoginActivity等。

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. 我经常将其重命名为XManager以避免混淆(例如ProductManagerMediaManager ......),因此演示者类仅用于保持工作流程。

The rule of thumb is no or at least limit import android package in presenter class. 经验法则是没有或至少限制在演示者类中导入android包 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. 这个最佳实践支持您更轻松地测试presenter类,因为presenter现在只是一个普通的java类,所以我们不需要android框架来测试这些东西。

For example here is my mvp workflow. 例如,这是我的mvp工作流程。

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. 视图类 :这是一个存储所有视图的位置,例如按钮,textview ...并且您在此图层上设置这些视图组件的所有侦听器。 Also on this View, you define a Listener class for presenter implements later. 此视图上,您​​还可以在以后为演示者实现定义一个Listener类。 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. Presenter类:这是您在里面存储视图和模型以便稍后调用的地方。 Also presenter class will implement ViewListener interface has defined above. 另外,presenter类将实现上面定义的ViewListener接口。 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. Manager类:这是核心业务逻辑代码。 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 . 通常我们通过一些注入框架(如Dagger获取Context类。

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. 此设计将使您的代码更加健壮,以后更容易修改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM