2015-12-13 39 views
33

我有一个有两个片段的活动。有多个片段的MVP活动

活动(MainActivity)从露天天气api中检索数据。我已经实现MVP此,其中: Model包含了从API
View所有响应对象是Activity
Presenter包含MainPresenterMainPresenterImplMainViewGetDataInteractorGetDataInteractorImpl

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

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

+1

Just a我认为:我认为片段被视为视图(关于MVP),因此我想知道让一个演示者引用多个视图(或者更确切地说:他们的界面回调)在视图中最合适地显示不同的数据是很奇怪的为了那个原因?我认为演示者需要决定/指导哪个视图显示哪些数据?P.s。显然,一个视图的多个主持人是一种有效的方法,所以也许另一种方式也可以工作:http://stackoverflow.com/a/2068/1041533 – AgentKnopf

+2

@AgentKnopf实际上,如此处所述http://programmers.stackexchange.com/a/261351/206366在MVP中,每位演示者负责呈现一个视图。演示者可以呈现多个视图的唯一方式是,如果不同的视图仅仅是绑定到演示者的单个视图界面的不同实现。 – Ari

+0

@Ari谢谢你的跟进 - 这确实有道理! – AgentKnopf

回答

12

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

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

演示者应负责调用api服务。

因此,主持人应该公开一个方法,如loadXXX,在内部它会打电话给服务。收到回复后,发言人应该拨打view.showXXX以获得服务结果。活动/片段应调用此方法并实施showXXX

通常,演示者被创建或注入到活动/片段中。 活动/片段必须实现演示者公开的接口,并且演示者持有该接口的弱引用,以便它可以回调。

当用户与屏幕交互时,例如按钮上的onClick,活动/片段调用演示者中的相应方法,例如, presenter.loadUserDetails()演示者告诉视图显示为加载,例如, view.showAsLoading(),因为它必须做它的东西:也许验证一些东西或从api服务加载数据并最终回调结果到视图,例如, view.showUserDetails(userDetails)

总之,例如,在MVP中的各个部分的代码:

活动/片段仅表示了MVP视野:

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); 
    } 

} 
+0

先生,你能解释为什么mWeakView是一个WeakReference,原因是什么? –

+1

这是为了避免保留对活动/片段的引用。演示者向API发出异步请求。如果在演示者发出请求时按下或完成活动,而您未使用WeakReference,则演示者将保留活动/片段内存(保留活动/片段的所有视图和成员)。代替使用WeakReference,在演示者中公开附加和分离方法也很常见。实例化演示者后,您应该调用attach方法,并且在调用Activity/Fragment的onDestroy时,应该调用detach。 – fernandospr

+0

如果您在演示者的请求完成之前未使用WeakReference或attach/dettach方法并且您的活动/片段已被销毁,那么当请求结束时您还可能遇到问题,因为它会尝试更新已销毁的内容活性/片段。 – fernandospr