Android MVP学习
2016-04-24 22:16
351 查看
一.概述
首先来介绍一下什么是MVPMVP是模型(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(); } }
最后给出代码下载地址
点此下载源码
相关文章推荐
- 《Android JNI》05 在JNI中调用Java的函数
- Android开发学习之路--RxAndroid之简单原理
- Android开发学习之路--RxAndroid之简单原理
- Android Studio中拦截电话的方法
- Android常见问题总结(二)
- android图片的处理
- Android的常用布局
- Android-SeekBar可滑动进度条
- Android内部File文件缓存
- android简单的书写
- Android触摸事件分发机制详解
- android支持缩放的图片浏览工具
- Android实现IOS向右滑动退出当前Activity
- Android获得应用包名
- android源代码编译
- android studio中导入samples
- Android学习笔记(42):SQLite数据库
- 将Eclipse代码导入到AndroidStudio的两种方式
- Android WebView 获取网页数据(html)
- 转:在Eclipse中关联Android Private Libraries中文件的源代码