具有多个片段的活动的 MVP
Posted
技术标签:
【中文标题】具有多个片段的活动的 MVP【英文标题】:MVP for Activity with multiple Fragments 【发布时间】:2016-03-19 09:26:51 【问题描述】:我有一个包含两个片段的活动。
活动 (MainActivity
) 从开放的天气 API 中检索数据。我为此实施了 MVP,其中:
Model
包含来自 API 的所有响应对象View
是 Activity
Presenter
包含 MainPresenter
、MainPresenterImpl
、MainView
、GetDataInteractor
和 GetDataInteractorImpl
。
因此,活动从 Web 服务获取数据。两个片段都将显示活动中检索到的数据中的数据。
在这种情况下使用 MVP 的最佳做法是什么?我知道如何通过接口/回调在片段 活动之间传递数据,我的问题是在实现 MVP 时这种行为会改变吗?
【问题讨论】:
只是一个想法:我会考虑将片段计为视图(关于 MVP),因此我想知道让一个演示者引用多个视图(或者更确切地说:它们的接口回调)是否会很奇怪) 在最适合的视图中显示不同的数据?我认为演示者需要决定/指导哪个视图显示哪些数据?显然,一个视图的多个演示者是一种有效的方法,所以也许另一种方法也可以:***.com/a/2068/1041533 @AgentKnopf 实际上,正如 MVP 中的 programmers.stackexchange.com/a/261351/206366 所述,每个演示者负责呈现一个视图。演示者可以呈现多个视图的唯一方法是,如果不同的视图只是绑定到演示者的单个视图接口的不同实现。 @Ari 感谢您的跟进 - 这确实有道理! 【参考方案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 的所有视图和成员)。除了使用 WeakReference,在演示者中公开附加和分离方法也很常见。实例化presenter后你应该调用attach方法,当Activity/Fragment的onDestroy被调用时,你应该调用detach。 如果您不使用 WeakReference 或附加/分离方法,并且您的活动/片段在演示者的请求完成之前被销毁,您也可能在请求完成时遇到问题,因为它会尝试在被破坏的活动/片段上更新一些东西。 我正在做附加/分离的事情。同样当应用暂停时,我正在停止所有网络通话,不知道是否正确 @ShobhitPuri 是的,绝对是。所有与 UI 相关的事情都必须在 View 层中完成:活动和片段。根据经验,您不应该在演示者中有任何 android 导入。以上是关于具有多个片段的活动的 MVP的主要内容,如果未能解决你的问题,请参考以下文章