我正在将我的应用程序迁移到MVP。已经从这个孔米克中获得了静态演示程序模式的提示。
这是我简单的MVP策略。为了简洁起见,删除了大多数样板和MVP侦听器。这个策略帮助我改变了方向,证明了我的背景过程。与正在完成活动的停顿相比,活动正确地从正常的暂停中恢复。而且,演示者只有应用程序上下文,因此它不保留活动上下文。
我不是java专家,这是我第一次尝试MVP,使用静态演示器让我感到不舒服。我是不是遗漏了什么?我的应用程序运行得很好,反应也更快了。
视图
public class MainActivity extends Activity{
private static Presenter presenter;
protected void onResume() {
if (presenter == null)
presenter = new Presenter(this.getApplicationContext());
presenter.onSetView(this);
presenter.onResume();
}
protected void onPause() {
presenter.onSetView(null);
if(isFinishing())presenter.onPause();
}
}演示者
public class Presenter {
private MainActivity view;
Context context;
public Model model;
public Presenter(Context context) {
this.context = context;
model = new Model(context);
}
public void onSetView(MainActivity view) {
this.view = view;
}
public void onResume(){
model.resume();
}
public void onPause(){
model.pause();
}
}模型
public class Model {
public Model(Context context){
this.context = context;
}
public void resume(){
//start data acquisition HandlerThreads
}
public void pause(){
//stop HandlerThreads
}
}发布于 2015-08-16 05:34:21
我建议两件事。
Model、View和Presenter转换为接口。Activity、Fragment或View)应该非常简单,不需要进行测试。
作为接口的一个例子:
interface MVPView {
void setText(String str);
}
interface MVPPresenter {
void onButtonClicked();
void onBind(MVPView view);
void onUnbind();
}MVPPresenter类现在不依赖于Android:
class MyPresenter implements MVPPresenter{
MVPView view;
@Override void bind(MVPView view){ this.view = view; }
@Override void unbind() {this.view = null; }
@Override void onButtonClicked(){
view.setText("Button is Clicked!");
}
}Presenter成为一个静态类,而是将它变成一个保留的片段。当不需要静态对象时,需要小心地跟踪它们,并手动删除它们(否则会被认为是内存泄漏)。通过使用fragment片段,可以更容易地控制演示者的生命周期。当拥有保留片段的片段完成时,保留片段也会被销毁,内存可以被GC。看这里有个例子。发布于 2015-09-21 18:04:18
建议修改一下我的理解。:)
一个例子总是比语言更好,对吗?https://github.com/antoniolg
发布于 2016-04-22 12:52:52
您正处于正确的轨道上,询问static是正确的--每当您注意到您已经编写了该关键字时,就该暂停和反思了。
演示者的生命应该直接与活动的/片段联系在一起。因此,如果活动被GC清除,那么演示者也应该这样做。这意味着您不应该在演示者中保存对ApplicationContext的引用。在演示程序中使用ApplicationContext是可以的,但是当活动被销毁时,中断这个引用是很重要的。
演示者还应该将View作为构造函数参数:
public class MainActivity extends Activity implements GameView{
public void onCreate(){
presenter = new GamePresenter(this);
}
}主持人看起来:
public class GamePresenter {
private final GameView view;
public GamePresenter(GameView view){
this.view = view;
}
}然后,可以将活动LifeCycle事件通知演示者,如下所示:
public void onCreate(){
presenter.start();
}
public void onDestroy(){
presenter.stop();
}或者在onResume/onPause --试着保持对称。
最后,您只有3个文件:
(我从我给这里的另一个解释中提取了一些代码,但想法是一样的。)
GamePresenter:
public class GamePresenter {
private final GameView view;
public GamePresenter(GameView view){
this.view = view;
NetworkController.addObserver(this);//listen for events coming from the other player for example.
}
public void start(){
applicationContext = GameApplication.getInstance();
}
public void stop(){
applicationContext = null;
}
public void onSwipeRight(){
// blah blah do some logic etc etc
view.moveRight(100);
NetworkController.userMovedRight();
}
public void onNetworkEvent(UserLeftGameEvent event){
// blah blah do some logic etc etc
view.stopGame()
}
}我不清楚为什么要使用ApplicationContext而不是活动上下文,但是如果没有特殊的原因,那么可以将void start()方法更改为void start(Context context),只需使用活动的上下文即可。对我来说,这更有意义,也排除了在应用程序类中创建单例的需要。
GameView
是一个接口
public interface GameView {
void stopGame();
void moveRight(int pixels);
}GameFragment是一个扩展Fragment并实现GameView的类,它有一个GamePresenter作为成员。
public class GameFragment extends Fragment implements GameView {
private GamePresenter presenter;
@Override
public void onCreate(Bundle savedInstanceState){
presenter = new GamePresenter(this);
}
}这种方法的关键是清楚地理解每个文件的角色。
片段控制与视图相关的任何东西(按钮、TextView等)。它向演示者通知用户交互。
--演示者是引擎,它从视图获取信息(在本例中是片段,但注意到这种模式很适合依赖注入吗?这不是巧合。演示者不知道View是一个片段--它不在乎),并将其与从‘下面’接收到的信息(通信、数据库等)结合在一起,然后相应地命令View。
视图只是演示者与视图通信的一个接口。注意,方法读取为命令,而不是作为问题(例如getViewState())和not通知(例如onPlayerPositionUpdated()) -命令(例如movePlayerHere(int位置))。
https://stackoverflow.com/questions/32031724
复制相似问题