Android MVP架构的使用

前言

在现实项目中,我们经常会遇到这样一种情况,就是一个Activity类不仅要处理几种业务逻辑,同时还要兼顾着数据的请求以及UI的操作,这样造成的后果就是整个类的代码会出现上千行,更有胜者是几千行。显而易见,这种处理方式是不妥的,不仅违反了面向对象中单一职责原则,而且对于整个项目来说,也不利于项目的扩展和维护。(单一职责原则:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。)那么,面对这种情况,我们该如何去架构整个项目?由于android项目本身就是MVC架构的体现,Activity充当了Controller,所以我们需要一种新的架构去替代MVC。

MVP初步了解

MVP:(Model-View-Presenter)它是从MVC模式演变而来的,它与MVC模式相同的地方是,Controller/Presenter负责逻辑的处理,Model提供数据,View负责展示。作为一种新的模式,MVP与MVC有着一个重大的区别,在MVP中View并不直接使用Model,它们之间的通信是通过Presenter来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从Model中读取数据而不是通过Controller。

MVC图示

MVC

MVP图示

MVP

使用MVP的优点:

  • 模型与视图完全分离,我们可以修改视图而不影响模型
  • 可以更高效的使用模型,因为所有的交互都发生在一个地方,即Presendter内部
  • 我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常有用,因为视图的变化总是比模型的变化频繁。
  • 如果我们把逻辑放在Presenter中,那么我们就可以脱离用户来测试这些逻辑(单元测试)

MVP在Android中使用

  • View层负责处理用户时间和视图部分的展示,在Android中,它可能是Activity或者Fragment类
  • Model层负责访问数据。数据可以是远程Server API,本地数据库或者Share的Preference等
  • Presenter层是链接(或适配)View和Model的桥梁

示例

项目结构
这里写图片描述

定义一接口INewsView,作为View层和Presenter层关联的纽带,View层去实现该接口,而Presenter通过INewsView进行改变Activity的UI,同时Presenter类也和Model层进行关联操作
INewsView接口

public interface INewsView {
    void initView();//初始化控件

    void startLoad();//开始请求数据

    void loadSuccess(List<NewsBean> newsBeanList);//请求成功,数据不为空

    void loadFail();//请求失败

    void loadEmpty();//请求成功,数据为空

}

Activity类去实现该接口,进行UI逻辑操作

public class MainActivity extends AppCompatActivity implements INewsView{

    private NewsPersenter newsPersenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        newsPersenter = new NewsPersenter(this);
        newsPersenter.requestData();
    }

    @Override
    public void initView() {
        //初始化控件
    }

    @Override
    public void startLoad() {
        //请求数据前UI操作
    }

    @Override
    public void loadSuccess(List<NewsBean> newsBeanList) {
        //请求成功,数据不为空,UI操作
    }

    @Override
    public void loadFail() {
        //请求失败,UI操作
    }

    @Override
    public void loadEmpty() {
        //请求成功,数据为空,UI操作
    }
}

NewsPresenter类

public class NewsPersenter {
    private INewsView iNewsView;

    public NewsPersenter(INewsView iNewsView) {
        this.iNewsView = iNewsView;
        this.iNewsView.initView();
    }

    public void requestData() {
        //请求数据前数据前UI操作
        iNewsView.startLoad();
        //请求数据,异步请求
        NewsHttpRequest.requestNewsList(new Callback<List<NewsBean>>() {
            @Override
            public void onResponse(Response<List<NewsBean>> response) {
                if (response == null || response.body() == null || response.body().isEmpty()) {
                    //请求成功,无数据
                    iNewsView.loadEmpty();
                } else {
                    //请求成功,有数据
                    iNewsView.loadSuccess(response.body());
                }
            }

            @Override
            public void onFailure(Throwable t) {
                //请求失败
                iNewsView.loadFail();
            }
        });
    }
}

NewsHttpRequest类,进行数据请求,Model层操作

public class NewsHttpRequest {

    public static interface INewsRequest {
        @GET("/NewsService/newsList")
        Call<List<NewsBean>> getNewsBeanList();
    }

    public static void requestNewsList(Callback<List<NewsBean>> callBack) {
        Retrofit retrofit = new Retrofit.Builder().baseUrl("http://localhost:8080")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        retrofit.create(INewsRequest.class).getNewsBeanList().enqueue(callBack);
    }
}

ps:当项目比较小,业务逻辑不多的时候,不建议使用MVP模式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章