Android MVP学习

一.概述

首先来介绍一下什么是MVP
MVP是模型(Model)、视图(View)、主持人(Presenter)的缩写,分别代表项目中3个不同的模块。
  模型(Model):负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等;
  视图(View):负责界面数据的展示,与用户进行交互;
  主持人(Presenter):相当于协调者,是模型与视图之间的桥梁,将模型与视图分离开来。
  如下图所示,View与Model并不直接交互,而是使用Presenter作为View与Model之间的桥梁。其中Presenter中同时持有Viwe层以及Model层的Interface的引用,而View层持有Presenter层Interface的引用。当View层某个界面需要展示某些数据的时候,首先会调用Presenter层的某个接口,然后Presenter层会调用Model层请求数据,当Model层数据加载成功之后会调用Presenter层的回调方法通知Presenter层数据加载完毕,最后Presenter层再调用View层的接口将加载后的数据展示给用户。这就是MVP模式的整个核心过程。
  这里写图片描述

 这样分层的好处就是大大减少了Model与View层之间的耦合度。一方面可以使得View层和Model层单独开发与测试,互不依赖。另一方面Model层可以封装复用,可以极大的减少代码量。当然,MVP还有其他的一些优点,这里不再赘述。下面看下MVP模式在具体项目中的使用。 这样分层的好处就是大大减少了Model与View层之间的耦合度。一方面可以使得View层和Model层单独开发与测试,互不依赖。另一方面Model层可以封装复用,可以极大的减少代码量。当然,MVP还有其他的一些优点,这里不再赘述。下面看下MVP模式在具体项目中的使用。

二.MVP在项目中的应用

下面以一个请求天气信息的例子来看一下MVP的具体应用。
先看效果图

这里写图片描述

1.View层
天气信息模块主要展示从网络获取到的天气信息,View层的接口大概需要如下方法:
(1)显示正在加载数据的进度条
(2)请求成功隐藏进度条
(3)失败显示错误信息
(4)设置获取到的天气信息

public interface WeatherView {
    void showLoading();
    void hideLoading();
    void showError();
    void setWeatherInfo(Call<WeatherInfo> call, Response<WeatherInfo> response);
}

在信息展示页面实现这个接口

public class MainActivity extends AppCompatActivity implements WeatherView {
    @Bind(R.id.et_citynumber)
    EditText mEtCitynumber;
    @Bind(R.id.textview)
    TextView mTextview;
    Dialog dialog;
    //View层持有presenter层的引用
    private WeatherPresenterImpl mWeatherPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        dialog = new ProgressDialog(this);
        dialog.setTitle("正在加载中");
        mWeatherPresenter = new WeatherPresenterImpl(this);
    }
    public void click(View view){
        String number = mEtCitynumber.getText().toString();
        mWeatherPresenter.getWeatherInfo(number);
    }

    @Override
    public void showLoading() {
        dialog.show();
    }

    @Override
    public void hideLoading() {
        dialog.dismiss();
    }

    @Override
    public void showError() {
        Toast.makeText(this, "error", Toast.LENGTH_SHORT).show();
    }

    /**
     * 获取数据成功后会调用此方法,此方法的调用处在presentImpl的onResponse方法里
     * @param call
     * @param response
     */
    @Override
    public void setWeatherInfo(Call<WeatherInfo> call, Response<WeatherInfo> response) {
        WeatherInfo weatherInfo = response.body();
        mTextview.setText(weatherInfo.toString());
    }
}

2.Model层
model层主要负责从网络获取数据,model接口如下

/**
 * 抽象模型,定义了访问数据的方法,方法中持有presenter一个接口的引用,目的就是为了方便回调
 */
public interface WeatherModel {
    void loadWeather(String cityId, OnWeatherListener weatherListener);
}

model接口的实现如下

/**
 * 模型的实现类,具体对数据进行操作
 */
public class WeatherModelImpl implements WeatherModel {
    @Override
    public void loadWeather(String cityId, final OnWeatherListener weatherListener) {
        DemoApi demoApi = RetrofitWrapper.getInstance().create(DemoApi.class);
        Call<WeatherInfo> weatherInfo = demoApi.getWeatherInfo(cityId);
        weatherInfo.enqueue(new Callback<WeatherInfo>() {
            @Override
            public void onResponse(Call<WeatherInfo> call, Response<WeatherInfo> response) {
            //通过weatherListener回调将Modle层处理好的数据交给Presenter层
                weatherListener.onResponse(call,response);
            }

            @Override
            public void onFailure(Call<WeatherInfo> call, Throwable t) {
                weatherListener.onFailure(call,t);
            }
        });
    }
}

3.presenter层
View层需要调用presenter层获取数据,所以presenter层要提供一个接口

public interface WeatherPresenter {
    /**
     * 获取天气的信息,
     * @param cityId
     */
    void getWeatherInfo(String cityId);
}

同时要提供一个接口给Modle层回调

public interface OnWeatherListener {
    /**
     * 在presenter层实现,给Model层回调,更改view的状态,确保model层不直接操作view层
     * @param call
     * @param response
     */
    void onResponse(Call<WeatherInfo> call, Response<WeatherInfo> response);
    void onFailure(Call<WeatherInfo> call, Throwable t);
}

在presentImple的构造方法中,我们传进来一个View层的对象,同时创建一个modelImpl的对象,目的就是为了调用获取数据的方法。


/**
 * 实现了接口,给View层回调
 */
public class WeatherPresenterImpl implements WeatherPresenter,OnWeatherListener{
    /**
     * presenter层持有model层和view层的引用
     */
    private WeatherModelImpl mWeatherModelImpl;
    private WeatherView mWeatherView;

    /**
     * 此方法在View层调用
     * @param weatherView
     */
    public WeatherPresenterImpl(WeatherView weatherView){
        this.mWeatherView = weatherView;
        mWeatherModelImpl = new WeatherModelImpl();
    }

    /**
     * 此方法在view层调用
     * @param cityId
     */
    @Override
    public void getWeatherInfo(String cityId) {
        mWeatherView.showLoading();
        //model层获取数据
        mWeatherModelImpl.loadWeather(cityId,this);
    }

    /**
     * model层请求成功后会回调此方法
     * @param call
     * @param response
     */
    @Override
    public void onResponse(Call<WeatherInfo> call, Response<WeatherInfo> response) {
        mWeatherView.hideLoading();
        mWeatherView.setWeatherInfo(call,response);
    }
    /**
     * model层请失败后会回调此方法
     * @param call
     * @param response
     */
    @Override
    public void onFailure(Call<WeatherInfo> call, Throwable t) {
        mWeatherView.hideLoading();
        mWeatherView.showError();
    }
}

最后给出代码下载地址
点此下载源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值