Android MVP从Presenter打开Activity,反模式?

Jos*_*hon 32 mvp android

如果从Presenter层打开一个反模式,它会是一个反模式Activity吗?

如果是这样,我应该从视图层管理应用程序的导航吗?

Sae*_*umi 38

是的,这是一个反mvp模式.基于MVP中的被动视图,您失去了可测试性,因为您不必在演示者中处理Android框架.

因此,最好从视图层管理应用程序的导航.

class MyPresenter {
    MyPresenter.View view;

    void backButtonClicked() {
        view.navigateToHomeScreen();
    }

    public interface View {
        void navigateToHomeScreen();
    }
}

class MyActivity extends Activity implements MyPresenter.View {
    @Override
    void navigateToHomeScreen() {
        startActivity(...)
    }

    @OnClick(R.id.my_button)
    void onClick() {
        presenter.backButtonClicked();
    }
} 
Run Code Online (Sandbox Code Playgroud)

这种方式的另一个优点是可以很容易地用片段或视图替换活动.

编辑1:

Morgwai说这种方式会打破关注和单一责任的分离,但你不可能在每个地方都有单一的责任.有时你需要违反它.以下是Google针对MVP的示例:

TaskDetailPresenter调用ShowEditTask它负责打开一个新的Activity内部TaskDetailFragment.

但是你也可以使用CommandPattern,这是一种更好的方法

interface NavigationCommand {
    void navigate();
}
Run Code Online (Sandbox Code Playgroud)

因此,Presenter将在需要时使用它.


mor*_*wai 9

正如我在对已接受答案的评论中所写的那样,我认为从视图层管理导航是明确打破关注点分离规则:视图应该只包含更新当前UI屏幕的方法.

问题源于android平台设计Activity,Fragment类包含在UI屏幕上操作和发送启动其他活动的意图对象的方法startActivity.

解决这个问题的一个简洁方法是创建一些Navigator接口,其中包含与导航相关的方法,make活动实现它并将其注入到演示者中.这种方式至少可以从演示者的立场导航和UI操作中分离出来.然而,从活动的角度来看,它可能看起来很奇怪:现在他们经常实现两个接口(Navigator和View)并将它们的引用传递给演示者2次.如果由于这个原因您决定从视图层管理导航,那么至少将用于导航的方法与用于操作UI的方法分开:永远不要在同一方法中执行导航和UI操作.


Ale*_*der 6

在我看来,如果你从视图层打开一个活动会更好.我更喜欢Presenter尽可能少地了解Activity.

如果存在应该启动哪些活动的某些条件,您可以使用以下内容:

public class Presenter {

    private ViewsPresentation mViewsPresentation;

    public void someButtonClicked() {
        if (/*some condition*/) {
            mViewsPresentation.startFirstActivity();
        } else {
            mViewsPresentation.startSecondActivity();
        }
    }

    public interface ViewsPresentation {
        void startFirstActivity();
        void startSecondActivity();
    }

}
Run Code Online (Sandbox Code Playgroud)