您的位置:首页 > 移动开发 > Android开发

Android MVP学习

2016-04-24 22:16 351 查看

一.概述

首先来介绍一下什么是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();
}
}


最后给出代码下载地址

点此下载源码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: