在Android中应用MVP模式

来源:互联网 发布:卸载office2010的软件 编辑:程序博客网 时间:2024/06/05 05:09

MVP在Android项目中的应用已经不是什么新鲜事了,什么是MVP模式这里也不做详细说明,先上一张图:

这里写图片描述

View:Activities, Fragments and Widgets are all ‘Views’
Model:Data layer consists of Model objects, SQLite, API data, ContentProvider etc;
Presenter:Presenters get data from data layer and update Views. They alse respond to view events;

Make your presenters and your models non-android

这里稍提一下为什么有mvp模式,mvp解决的是什么问题?

在Android开发中,Activity并不是一个标准的MVC模式中的Controller,它的首要职责是加载应用的布局和初始化用户界面,并接受并处理来自用户的操作请求,进而作出响应。随着界面及其逻辑的复杂度不断提升,Activity类的职责不断增加,以致变得庞大臃肿。当我们将其中复杂的逻辑处理移至另外的一个类(Presneter)中时,Activity其实就是MVP模式中View,它负责UI元素的初始化,建立UI元素与Presenter的关联(Listener之类),同时自己也会处理一些简单的逻辑(复杂的逻辑交由Presenter处理).

同时,而在MVP模式中,处理复杂逻辑的Presenter是通过interface与View(Activity)进行交互的,这说明我们可以通过自定义类实现这个interface来模拟Activity的行为对Presenter进行单元测试。使得测试更加简单高效

最近公司新的一个项目准备用MVP模式,这是今天的主题。项目的目录结构查不多是下面这样:
这里写图片描述

这种项目结构我认为是比较清晰的。虽然这是一个小项目,不能真正体现MVP模式的优势,但是项目整体上我还是选择使用MVP模式,至于为什么?我想这篇文章:我们为什么要把Dagger2,MVP以及Rxjava引入项目中?,能比较好的帮我回答这个问题?项目基本结构就是这样,下面是主要结合到的一些第三方包。

  • dagger2 依赖注入框架
  • rxjava/rxandroid 响应式编程
  • retrofit 网络请求
  • ButterKnife JakeWharton的view注入框架

这里在Android Studio中有两个快速生成代码的插件:

  • Android ButterKnife Plugin Plus 可以快速生成注解View。
    安装重启AS后,在setContentView的布局文件上,按住Alt+Ins键就有相关快捷键。
  • Json2Class 通过json字符串快速生成对应的实体类。另外一个Json2Pojo在生成实体类时,属性名与json字符串中的属性名不一致(多了一个m),所以这里使用Json2Class。

并且我还加入了retrolambda用于支持java8中的lambda表达式,这个在使用rxjava就会有明显的体现,rxjava支持一些函数式编程风格的操作,特别在rxjava2中很多函数式接口名都与java8中是一致的。

关于rxjava的使用,前面也有相关文章RxJava初探。对于响应式这一点在项目中我也是有体会的。也就是说响应是被动的,只有被观察者有动静了,观察者才能响应,理解这一点对于编写出正确的程序是有帮助的。

dagger2在这些技术中应用起来可能大家觉得比较难的了。建议可以结合一些实例,再看看这篇文章,会有一个比较好的认识。
Component:把目标类依赖的实例注入到目标类中,来初始化目标类中的依赖。
Module:一个简单工厂模式,Module里面的方法基本都是创建类实例的方法。创建类实例有2个维度可以创建:

  • 通过用Inject注解标注的构造函数来创建(自己创建的类)
  • 通过工厂模式的Module来创建(第三方包提供的类)

同时作为依赖注入框架Spring相比于Dagger的不足之处:第一个是Spring仅能注入本身含有注解的类,而第二个是Spring无法区分通过泛型实现同一接口的类。

关于retrofit的使用,我前面的文章也有介绍Retrofit。如果需要深入,可以去看看源码。

关于后续项目中出现的问题和情况,我将保持更新。

遇到的问题:

  1. Fragment中嵌套多个Fragment ,使用ViewPager管理,会有View丢失情况,此时需要使用getChildFragmentManager()而不是getFragmentManager()。
    关于Fragment的另一个问题就是Fragment长期置于后台返回重叠的问题,当系统内存不足,Activity 被系统回收时,会主动调用 onSaveInstance() 方法来保存视图层(View Hierarchy)状态信息,当从后台返回重新创建Activity时,Fragment每个周期方法都走了两遍。这其实是创建了两个Fragment实例,这个两个Fragment一个是我代码里面主动创建的,另外一个则是上次Activity异常销毁时保存的。之前状态保存的 Fragment 依然会出现在 Activity 中,此时的 FragmentTransaction 中的相当于又再次 add 了 fragment 进去的,hide()和show()方法对之前保存的fragment已经失效了,所以就出现了重叠。
    知道这样原因问题就好解决了。

  2. 自定义一个简单的layout,onDraw(Canvas canvas)方法未执行,在构造函数中加上setWillNotDraw(false);

/**   * If this view doesn't do any drawing on its own, set this flag to   * allow further optimizations. By default, this flag is not set on   * View, but could be set on some View subclasses such as ViewGroup.   *   * Typically, if you override {@link #onDraw} you should clear this flag.   *   * @param willNotDraw whether or not this View draw on its own   */   public void setWillNotDraw(boolean willNotDraw) {       setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);   }  
0 0
原创粉丝点击