【问题标题】:MVP for Activity with multiple Fragments具有多个片段的活动的 MVP
【发布时间】:2016-03-19 09:26:51
【问题描述】:

我有一个包含两个片段的活动。

活动 (MainActivity) 从开放的天气 API 中检索数据。我为此实施了 MVP,其中: Model 包含来自 API 的所有响应对象
ViewActivity
Presenter 包含 MainPresenterMainPresenterImplMainViewGetDataInteractorGetDataInteractorImpl

因此,活动从 Web 服务获取数据。两个片段都将显示活动中检索到的数据中的数据。

在这种情况下使用 MVP 的最佳做法是什么?我知道如何通过接口/回调在片段 活动之间传递数据,我的问题是在实现 MVP 时这种行为会改变吗?

【问题讨论】:

  • 只是一个想法:我会考虑将片段计为视图(关于 MVP),因此我想知道让一个演示者引用多个视图(或者更确切地说:它们的接口回调)是否会很奇怪) 在最适合的视图中显示不同的数据?我认为演示者需要决定/指导哪个视图显示哪些数据?显然,一个视图的多个演示者是一种有效的方法,所以也许另一种方法也可以:stackoverflow.com/a/2068/1041533
  • @AgentKnopf 实际上,正如 MVP 中的 programmers.stackexchange.com/a/261351/206366 所述,每个演示者负责呈现一个视图。演示者可以呈现多个视图的唯一方法是,如果不同的视图只是绑定到演示者的单个视图接口的不同实现。
  • @Ari 感谢您的跟进 - 这确实有道理!

标签: android android-fragments interface mvp


【解决方案1】:

应将活动/片段视为 MVP 模型中的视图。这意味着他们应该只显示数据并接收用户交互。 可以通过接口/回调来交流活动和片段。

但是,调用 API 服务不是活动/片段的责任。

presenter 应该负责调用 api 服务。

因此,演示者应该公开一个类似loadXXX 的方法,在内部它会调用服务。收到响应后,演示者应使用服务结果调用view.showXXX。活动/片段应调用此loadXXX 方法并实现showXXX

通常,演示者被创建或注入到活动/片段中。 Activity/Fragment必须实现Presenter暴露的接口,Presenter持有该接口的弱引用,以便回调。

当用户与屏幕交互时,例如按钮上的onClick,activity/fragment 会调用presenter 中的相应方法,例如presenter.loadUserDetails() 演示者告诉视图显示为正在加载,例如view.showAsLoading() 因为它必须做自己的事情:可能验证某些内容或从 api 服务加载数据,最后将结果回调到视图,例如view.showUserDetails(userDetails).

总结,一个例子,在MVP的各个部分的代码中:

Activity/Fragment 仅代表 MVP 的 View:

public class MyActivity extends AppCompatActivity implements MyPresenter.View {
    private MyPresenter mPresenter;

    public onCreate() {
        ...
        mPresenter = new MyPresenter(this); // Or inject it and then set the view.
    }

    public void onClick(View v) {
        mPresenter.loadXXX(param1, param2);
    }

    // MyPresenter.View methods

    public void showAsLoading() {
        ...
    }

    public void showUserDetails(UserDetails userDetails) {
        ...
    }
}

型号:

public class UserDetails {
    ...
}

演讲者:

public class MyPresenter {

    private WeakReference<MyPresenter.View> mWeakView;

    public MyPresenter(MyPresenter.View view) {
        mWeakView = new WeakReference(view);
    }

    public void loadXXX(String param1, String param2) {
        MyPresenter.View view = mWeakView.get();
        if (view != null) {
            view.showAsLoading();
            // Do stuff, e.g. make the Api call and finally call view.showUserDetails(userDetails);
        }
    }

    interface View {
        void showAsLoading();
        void showUserDetails(UserDetails userDetails);
    }

}

【讨论】:

  • 先生,您能解释一下为什么 mWeakView 是 WeakReference,原因是什么?
  • 这是为了避免保留对 Activity/Fragment 的引用。演示者向 API 发出异步请求。如果您在演示者发出请求时按下或完成活动并且您不使用弱引用,则演示者将保留 Activity/Fragment 内存(保留该 Activity/Fragment 的所有视图和成员)。除了使用 Wea​​kReference,在演示者中公开附加和分离方法也很常见。实例化presenter后你应该调用attach方法,当Activity/Fragment的onDestroy被调用时,你应该调用detach。
  • 如果您不使用 Wea​​kReference 或附加/分离方法,并且您的活动/片段在演示者的请求完成之前被销毁,您也可能在请求完成时遇到问题,因为它会尝试在被破坏的活动/片段上更新一些东西。
  • 我正在做附加/分离的事情。同样当应用暂停时,我正在停止所有网络通话,不知道是否正确
  • @ShobhitPuri 是的,绝对是。所有与 UI 相关的事情都必须在 View 层中完成:活动和片段。根据经验,您不应该在演示者中有任何 android 导入。
猜你喜欢
  • 1970-01-01
  • 2018-12-03
  • 1970-01-01
  • 2017-05-26
  • 1970-01-01
  • 2017-11-20
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多