MVX Android设计架构浅析-MVP
2016-04-26 11:43
579 查看
简介
MVX Android设计架构浅析-MVC 读过这篇文章以后,应该对MVC框架有个大概的了解,这也是大部分Android应该的常用框架,但是这种框架给人的感觉更像是 View-Module框架,因为View层的确没有显现出来,而且View和Module的耦合度较高,到最后会像下图一样,业务逻辑和View展现紧密耦合在一起,相互交错,随着项目的壮大以后很难维护。![](http://7xinl9.com1.z0.glb.clouddn.com/20160425160440.png)
这么复杂的交互基本集中在Activity或者Fragment中,这样Controller每一部分都不能重复利用,无法轻易的测试、或者调试和重构。
如果使用MVP,那会是什么画面?
![](http://7xinl9.com1.z0.glb.clouddn.com/20160425160800.png)
复杂的任务被分成细小的任务,并且很容易解决。越小的东西,bug越少,越容易debug,更好测试。在MVP模式下的View层将会变得简单,所以即便是他请求数据的时候也不需要回调函数。View逻辑变成十分直接。
简化的交互图
经过上面的表述,我们体验到MVP的优势,所以这样有必要再温习一下MVP的交互图![](http://7xinl9.com1.z0.glb.clouddn.com/20160425150914.png)
代码
Talk is cheap,show me the code.(废话少说,直接上代码)读过MVX Android设计架构浅析-MVC这篇文章的同学都应该还记得,在层与层之间衔接最好是通过接口,所以我们不妨直接先定义接口
接口
View层(不仅仅局限于Android中的View,还有其他与用户交互的构件)public interface WeatherView { void showLoading(); void hideLoading(); void showError(); void setWeatherInfo(Weather weather); }
这个接口也清晰的说明了View层可以操作的方法和具有的功能
Module层(抽象数据层)
public interface WeatherModel { void loadWeather(String cityNO, OnWeatherListener listener); }
这个接口比较简单,就是单一的获取Remote/Local数据
Presenter层(主要的业务逻辑层)
public interface WeatherPresenter { void getWeather(String cityNO); }
这个接口主要是处理业务逻辑,完成中间的View和Module的桥接。
实现
View层(不仅仅局限于Android中的View,还有其他与用户交互的构件)public class WeatherActivity extends BaseActivity implements WeatherView, View.OnClickListener { private Dialog loadingDialog; private EditText cityNOInput; private TextView city; private TextView cityNO; private TextView temp; private TextView wd; private TextView ws; private TextView sd; private TextView wse; private TextView time; private TextView njd; private WeatherPresenter weatherPresenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init() { cityNOInput = findView(R.id.et_city_no); city = findView(R.id.tv_city); cityNO = findView(R.id.tv_city_no); temp = findView(R.id.tv_temp); wd = findView(R.id.tv_WD); ws = findView(R.id.tv_WS); sd = findView(R.id.tv_SD); wse = findView(R.id.tv_WSE); time = findView(R.id.tv_time); njd = findView(R.id.tv_njd); findView(R.id.btn_go).setOnClickListener(this); weatherPresenter = new WeatherPresenterImpl(this); //传入WeatherView loadingDialog = new ProgressDialog(this); loadingDialog.setTitle("加载天气中..."); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_go: weatherPresenter.getWeather(cityNOInput.getText().toString().trim()); break; } } @Override public void showLoading() { loadingDialog.show(); } @Override public void hideLoading() { loadingDialog.dismiss(); } @Override public void showError() { //Do something Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_SHORT).show(); } @Override public void setWeatherInfo(Weather weather) { WeatherInfo info = weather.getWeatherinfo(); city.setText(info.getCity()); cityNO.setText(info.getCityid()); temp.setText(info.getTemp()); wd.setText(info.getWD()); ws.setText(info.getWS()); sd.setText(info.getSD()); wse.setText(info.getWS()); time.setText(info.getTemp()); njd.setText(info.getNjd()); } }
View成的实现类,里面没有设计任何业务逻辑,L14 可以看出
View持有
WeatherPresenter的实例。而L38
weatherPresenter = new WeatherPresenterImpl(this)又可以看出
WeatherPresenter同样会持有
View的引用。所以
View和
Presenter之间是紧耦合。不过这里都是通过接口来减轻这种耦合度,并且有利于以后的代码维护。
Module层(抽象数据层)
public class WeatherModelImpl implements WeatherModel { @Override public void loadWeather(String cityNO, final OnWeatherListener listener) { /*数据层操作*/ VolleyRequest.newInstance().newGsonRequest("http://www.weather.com.cn/data/sk/" + cityNO + ".html", Weather.class, new Response.Listener<Weather>() { @Override public void onResponse(Weather weather) { if (weather != null) { listener.onSuccess(weather); } else { listener.onError(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { listener.onError(); } }); } }
Module实现类比较单一,就是获取Remote/Local数据,还有一些数据解析和数据封装操作也可以通过这层去实现,另外Android是UI线程非安全的,所以如果通过子线程获取Remote/Local数据,那么更新UI的操作必然不能直接进行,只能通过主线程去更新UI,所以这里讲Module和View分层也是很有道理的。
Presenter层(主要的业务逻辑层)
public class WeatherPresenterImpl implements WeatherPresenter, OnWeatherListener { /*Presenter作为中间层,持有View和Model的引用*/ private WeatherView weatherView; private WeatherModel weatherModel; public WeatherPresenterImpl(WeatherView weatherView) { this.weatherView = weatherView; weatherModel = new WeatherModelImpl(); } @Override public void getWeather(String cityNO) { weatherView.showLoading(); weatherModel.loadWeather(cityNO, this); } @Override public void onSuccess(Weather weather) { weatherView.hideLoading(); weatherView.setWeatherInfo(weather); } @Override public void onError() { weatherView.hideLoading(); weatherView.showError(); } }
通过这个
Presenter类可以看到仅仅有业务逻辑,而不会有UI和数据先关的东西在里面。同时也可以看出,这个类更多的是在桥接
View和
Module层,并没有做其他多余的操作。另外
Module层通过回调到
Presenter,然后通过
Presenter通知
View层更新UI,这个回调就是上面的
OnWeatherListener,当然如果想让这种耦合关系变得极其简单,可以通过
EventBus处理。
前面说了很多MVP的好话,这里不得不给他破一点凉水,实际开发过程中会有个不大不小的坑。
Activity会在很多情况下被系统重启:
- 当用户旋转屏幕
- 在后台时内存不足
- 改变语言设置
- attache 一个外部显示器等。
一旦重启以后,Presenter如何处理成为一个问题,大体的处理思路如下图所示
![](http://7xinl9.com1.z0.glb.clouddn.com/1233754-a9a829de0250462f.png)
前两种就不细说了,关于第三种处理方案可以详细参考 通过Loader延长Presenter生命周期
另外本文参考了 Android MVP 详解(上) 该文总结的很逆天,再次佩服作者的无私奉献精神。
附:
MVX Android设计架构浅析
MVX Android设计架构浅析-MVC
MVX Android设计架构浅析-MVP
MVX Android设计架构浅析-MVVM
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories