AndroidCodingAndroid知识Android开发

MVP在Android中简易易懂的实现案例

2017-03-08  本文已影响218人  Swy2w

前言

最进想做了一个新的小项目,总想来点对自己来说新鲜的东西。后面看到Google老大推荐使用MVP架构,顿时觉得不试试看都不好说是羡慕它的小弟了。良心大哥也专门在Github推出了一个项目Android Architecture Blueprints,用来展示Android用各种的MVP框架,也能算了官网教程了。在网络收集资料看了一下大神们的分析后,自己动手试了试。那么就马上上手来看一看MVP究竟如何。(本文都是围绕项目中todo-mvp部分来介绍

MVP模式

先上一张图,然后根据实际的代码我们来讲讲Google是怎么看待MVP架构的


基类

首先丁一两个Base接口,分别是作为Presenter和View的基类

public interface BaseView<T> {
    // 为View设置Presenter
    void setPresenter(T presenter);
    // 初始化界面控件
    void initView(View view);
}
public interface BasePresenter {
    // 获取数据并改变界面显示,在todo-mvp的项目中的调用时机为Fragment的OnResume()方法中
    void start();
}

契约类

官方事例中加如契约类来统一管理View和Presenter。这样整个功能可以在契约类一目了然。老大就是老大,这一点还是很厉害的。事例如下:

public interface YourContract {
    interface View extends BaseView<Presenter>{
        //这里加View功能方法
        void showError();
        void showLoading();
        void Stoploading();

    }
    interface Presenter extends BasePresenter{
        // 同上
        void loatPosts(int PagerNum,boolean cleaing);
        void  reflush();
        void loadMore(int PagerNum);
    }
}

对了,其中BaseView中含方法setPresenter,该方法作用是在将presenter实例传入view中,其调用时机是presenter实现类的构造函数中。如下

public YourPresenter(Context context, YourContract.View view) {
        this.context=context;
        this.view=view;
        this.view.setPresenter(this);
    }

Activity的作用

在讲这个之前,不知道大家有没有注意到上没图中,Fragment是作为View层而Activity是作为Presenter的,有没有想过Google为什么要推荐这样做呢?

MVC中Activity的作用

按照我们之前的习惯或者说在MVC模式中,Activity是作为View层和用户打交道,接收用户数据的输入和输出的。特别是我们会在Activity的声明周期中写入一些逻辑来实现我们想要的效果。这样很方便,但是后果是我们的Activity特别的臃肿,想一想如果我们一些通用的功能每个Activity里都要写一次不是一件很痛苦的事情。
这个时候,Activity 不仅承担了 View 的角色,还承担了一部分的 Controller 角色,这样一来 V 和 C 就耦合在一起了,虽然这样写方便,但是如果业务调整的话,要维护起来就难了,而且在一个臃肿的 Activity 类查找业务逻辑的代码也会非常蛋疼,所以看起来有必要在 Activity 中,把 View 和 Controller 抽离开来,而这就是 MVP 模式的工作了。

MVP中View层的实现

至于为什么要选择Fragment作为View层的实现类。我看到网上有这两种说法,第一个原因是我们把activity作为一个全局控制类来创建对象,把fragment作为view,这样两者就能各司其职。第二个原因是因为fragment比较灵活,能够方便的处理界面适配的问题

MVP 把 Activity 中的 UI 逻辑抽象成 View 接口,把业务逻辑抽象成 Presenter 接口,Model 类还是原来的 Model。

来看一段代码就能知道Activity的作用了(毕竟代码能够一目了然):

     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        if (savedInstanceState!=null){
            mainFragment= (MainFragment) getSupportFragmentManager().getFragment(savedInstanceState,"MainFragment");
            bookmarksfragment=(BookmarksFragment) getSupportFragmentManager().getFragment(savedInstanceState,"BookmarksFragment");
        }else {
            mainFragment=MainFragment.newInstance();
            bookmarksfragment=BookmarksFragment.newInstance();
        }
        new BookmarksPresenter(MainActivity.this,bookmarksfragment);
}

看了上面的代码大概就能知道Activity的作用是什么了。主要是作为全局的控制,负责创建View以及Presenter实例,并将二者联系起来。

View层的实现

   public class YourFragment extends Fragment implements YourContract.View {

    private YourContract.Presenter presenter;
    @Override
    public void onResume() {
        super.onResume();
        presenter.start();
    }
   @Override
       public void setPresenter(YourContract.Presenter presenter) {
           if (presenter!=null){
               this.presenter=presenter;
           }
       }
  @Override
    public void showError() {
        Snackbar.make(fab, R.string.loaded_failed,Snackbar.LENGTH_INDEFINITE)
                .setAction(R.string.retry, new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        presenter.reflush();
                    }
                })
                .show();
    }

  @Override
    public void showLoading() {
        refresh.post(new Runnable() {
            @Override
            public void run() {
                refresh.setRefreshing(true);
            }
        });
    }

    @Override
    public void Stoploading() {
        refresh.post(new Runnable() {
            @Override
            public void run() {
                refresh.setRefreshing(false);
            }
        });
    }
}

可以看到通过setPresenter方法获取到Presenter的实例。然后在Fragment的生命周期中调用presenter.start()方法。这样View层只负责数据给用户呈现他们看到的东西,而不去管具体是怎样实现的(ps:我觉得在onResume()方法之前调用应该都行吧,不知道是不是对的。如果有错,还请指教)

Presenter层的实现

public class YourPresenter implements YourContract.Presenter {
public YourPresenter(Context context, YourContract.View view) {
        this.context=context;
        this.view=view;
        this.view.setPresenter(this);
    }

@Override
    public void loatPosts(int PagerNum, final boolean cleaing) {
        //具体实现就不贴了,有点长
}
@Override
    public void start() {
        loatPosts(CurrentPagerNum,true);
    }

@Override
    public void reflush() {
        loatPosts(CurrentPagerNum,true);
    }

@Override
    public void loadMore(int PagerNum) {
        loatPosts(CurrentPagerNum+PagerNum,false);
    }
}

在构造方法中,Presenter将自身的事例传递给了View,这样View就能调用Presenter层的方法来处理业务逻辑了。在start()方法中,处理了数据加载。

Model层的实现

项目中model层最大的特点是被赋予了数据获取的职责,与我们平常model层只定义实体对象截然不同,实例中,数据的获取、存储、数据状态变化都是model层的任务,Presenter会根据需要调用该层的数据处理逻辑并在需要时将回调传入。这样model、presenter、view都只处理各自的任务,此种实现确实是单一职责最好的诠释。

总结

MVP的好处

以上就是我这段时间来对MVP的理解了。如果有错误的地方,欢迎指教哦。

上一篇下一篇

猜你喜欢

热点阅读