Android中的MVP设计模式问题

4

我正在研究MVP,并考虑在我的下一个项目中使用这种设计模式。 但是我在使用这种设计模式时遇到了问题。

请看下面的Java代码。

我有一个BaseActivity类

public class BaseActivity extends AppCompatActivity {

}

一个接口 BaseView
public interface BaseView {

void showLoader();
void hideLoader();

}

一个扩展了BaseView接口的接口,用于维护视图之间的关系。
//Game start from here
public interface TestView extends BaseView {
    void showResult();
}

这是最终的活动:
public class MyTestActivity extends BaseActivity implements TestView {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_test);
     }

    @Override
    public void showLoader() {

    }

    @Override
    public void hideLoader() {

    }

    @Override
    public void showResult() {

    }
}

BaseView中的showLoader()和HideLoader()方法对于每个扩展BaseView的接口都是常见的。这就是为什么我将它们保留在BaseView中的原因。到目前为止还没有问题。

问题是:我必须在每个实现BaseView或其子接口的类中实现和提供这些方法的定义。

例如:在这里

TestActivity extends BaseActivity implements TestView 

为了避免这个问题,我在BaseActivity中实现了BaseView,并提供了这些方法的定义。但是如果我在BaseActivity中实现了BaseView,我可以看到BaseView是从BaseActivity传递给TestActivity的。
而且TestView已经实现了BaseView,这是我的要求,TestView必须扩展BaseView。如果我不在BaseActivity中实现BaseView,则需要在每个Activity类中实现showLoader()和hideLoader()方法。目前在BaseView中有2个方法,它们可以更多......
请建议任何解决方案。
2个回答

2
只需在BaseActivity中实现默认实现即可。因此,如果需要,您可以在子类中覆盖方法。请保留HTML标记,但不要写解释。
BaseActivity implements BaseView

我的要求是TestView必须扩展BaseView。 - Ankit Saini
一切应该正常工作:TestView 扩展 BaseView -- BaseActivity 实现 BaseView -- TestActivity 扩展 BaseActivity 并实现 TestView - CeH9
在这种情况下,BaseView 将在 TestActivity 中重复出现,这违反了标准。 - Ankit Saini
Java中的interface仅仅是"实现一些方法"的契约,而不是"违背标准"。 - CeH9
此外,您可以将您的BaseActivity设置为抽象类,以仅实现BaseView方法的一部分。 - CeH9

1
我将实现MVP的方法如下:
您需要有BaseView和BasePresenter。然后,您需要在View和Presenter之间建立一个合同,该合同具有其自己的接口,扩展了您的BaseView和BasePresenter。我将如下所示:
示例活动(ExampleActivity)。
public class ExampleActivity extends BaseActivity implements ExampleContract.View {
     private ExampleContract.Presenter presenter;

     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_example);

         presenter = new ExamplePresenter(this);
         presenter.start();
    }

    @Override
    public void setPresenter(ExampleContract.Presenter presenter) {
         this.presenter = presenter;
    }
}

ExamplePresenter
public class ExamplePresenter implements ExampleContact.Presenter {
     private ExampleContract.View exampleView;

     public ExamplePresenter(ExampleContract.View exampleView) {
         this.exampleView = exampleView;
         exampleView.setPresenter(this)
     }

     @Override
     public void start() {
         //do nothing for now
     }
}

ExampleContract。
public interface ExampleContract {

    interface View extends BaseView<Presenter> {

    }

    interface Presenter extends BasePresenter {

    }

}

BaseView
public interface BaseView<T> {
    void setPresenter(T presenter);
}

BasePresenter

public interface BasePresenter {
    void start();
} 

那么我们可以从中得出什么结论,它们之间又如何联系?

  • 如果您想要所有合同(而不是视图)的共享实现,即我所有的视图和展示器都将在整个应用程序中具有setPresenter(T presenter)调用和start()调用,则将其添加到您的BaseViewBasePresenter中。
  • 然后,在您的合同中,您的View接口和Presenter接口(各个活动将实现该接口),将具有其自己的功能,适用于您想要实现的活动。
  • 然后,通过在onCreate中将自身传递给Presenter的构造函数,将Presenter链接到视图,然后在Presenter的构造函数内部,它将通过设置Presenter回调到视图。它们现在通过绑定合同彼此分配。现在,您只需在View接口和Presenter接口中添加方法即可。

我正在做完全相同的事情,再次遇到BaseView和ExampleContract.View的问题,在Activity中我必须实现所有方法。 - Ankit Saini
如果BaseActivity提供了BaseView方法的定义,我将写更少的代码。 - Ankit Saini
MVP 不是关于写更少的代码,而是关于编写可测试的代码。如果你担心写更多的代码,可以在 BaseActivity 类中编写一个受保护的方法,并在需要时从子类中调用它。但是,你需要在 presenter 和 view 之间建立一个契约。或者像 senya 上面所说的那样,将基类设置为抽象类,并选择要实现的内容。 - Bradley Wilson
好的,我完全同意你的观点。但是我不想在每个Activity中都定义BaseView方法。这不是关于代码大小,而是关于代码重复性。有什么建议吗? - Ankit Saini

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接