我们为什么要把Dagger2,MVP以及Rxjava引入项目中?

Why?(文章最后有惊喜)

我们为什么要把Dagger2,MVP以及Rxjava引入项目中?

  • 毫无疑问在Android开发圈中这三个技术是经常被提及的,如此多的文章和开源项目在介绍他们,使用他们,开发者也或多或少的被带动起来在自己的项目中使用他们,但是使用他们之前我们知道为什么要使用他们,他们能给我们带来什么好处吗,还是只是跟随潮流

其实我们大多数项目中是使用不到他们的,或者说对这些技术的需求不是很大,为什么这么说呢?

  • 大多数的开发者其实都是在开发功能模块比较少的小项目,对于这些项目来说,其实使用这些技术带来的好处相对于在开发时的所付出的时间来说其实性价比并不高,因为学习这些会有个学习曲线,并且这些技术并不会让你的开发速度加快,相反会让你多写很多代码,比如MVPDagger都会让你多写很多类和接口

  • 所以说我们开发小项目根本是感觉不到这些技术给我们带来的好处,也会困惑我们为什么要引入这些技术?

那为什么这些技术会这么火呢?

  • 其实这些困惑大多出现在一直做功能模块比较少的小项目的开发者上,只要你做过比较大的项目,随着代码的增多你就会遇到代码的耦合,团队协作时冲突的解决,类依赖的复杂度等问题,其实这些技术就是来解决这些问题的,所以这些技术大项目用的非常多

这些技术出现是为了解决什么?

  • 想灵活运用一个技术,必然要了解这些技术为什么出现,出现是为了解决什么问题

MVP

MVP的文章很多,我这里就不做过多介绍,我个人的理解就是解耦和扩展以及团队协作,大多数文章都只是介绍了怎么写MVP接口,我们不懂为什么用他们,就算会写也只是在做复制粘贴

举个栗子

  • 我们需要用户点击按钮从网络获取一段新闻消息显示到TextView上,如果都在Activity中做这些事情,OK,非常爽,不用多写MVP相关的接口和类,啪啪啪一下就写完了

  • 但是我们现在需求变了,我们要加入缓存,并且不用TextView显示,使用Toast显示,现在去改Activity,虽然麻烦,但是没问题都是你写的,改改也没问题,但是这个如果不是你写的,你现在去改,要把逻辑重新看一遍,在重新修改之前的代码,如果逻辑一复杂,你重新看一遍逻辑要时间,并且如果改错的话,会影响之前已经写好的功能,这完全违背开闭原则

  • 但是我们用MVP去开发,就可以缩小这些问题,我们只需要在Model层加入缓存逻辑,因为Presenter层拿到的是Model的接口,他只关心Model层返回的数据,至于你的接口是怎么实现的,你的数据是从网络还是数据库还是本地文件获取的,根本不必关心

  • Presenter拿到的也是View的接口,PresenterModel获取完数据,返回给View,就完成了他的工作,他根本不用管View是怎么实现的,使用TextView显示还是Toast显示,这些都是View的事情,所以他们每层只用把各自的事情做好根本不用管以外的事情

  • 这样我们就可以把View,Presenter,Model拿给三个不同的人写,需求一变不会影响整个代码,将问题最小化,比如UI需求一变我们只用修改View层,出了问题可以马上定位,并且易于测试

Dagger

Dagger的门槛个人认为在这三个中是最高的,相关的文章也很多,但是都很多只是告诉你该怎么写这些类,注解该怎么用,很多都没讲为什么不直接new,为什么要把如此简单的事情弄这么复杂?其实这还是和项目的大小有关,因为它解决的问题就是大项目的需求

举个栗子

  • 我们现在需要一个类叫Car,Car中需要持有一个叫People的对象,People中又需要持有key对象,Ok,这还不简单
Car car = new Car(new People(new Key()));

  • 但是大型项目的实际情况是这样的

A a = new A();
B b = new B(a);

C c = new C(a,b);

D d = new D(c);

E e = new E(a,b,d);

  • 以上只是举个例子,构建一个E,还要构建一堆其他的对象,并且其他对象的构建同样复杂,并且必须按顺序构建,而且需要的对象的生命周期都不一样,有些生命周期可能和Activity一样,有些可能是单例,所以在构建的时候还要考虑对象声明周期,考虑对象的来源,在大型项目,这很痛苦,不光用起老火,别人看代码也和看天书一样

  • 所以这个时候依赖注入框架就派上用场了,我们只用专注于怎么实现功能,对象的依赖关系和生命周期,都让它来帮我们管理,一个Inject,它会按照依赖关系帮我们注入我们需要的对象,并且它会管理好每个对象的生命周期,在生命周期还没结束的情况下是不会重复new的,所以Dagger非常适合大项目,小项目开发者因为项目复杂度低,没遇到这些问题,所以不会理解为什么要用Dagger,让简单的new,变这么复杂

RxJava

提到Rxjava最多人都是用来处理,线程调度,回调地狱,加上Retrofit又支持Rxjava,所以大部分开发者都只会在请求网络和需要切换线程的时候用到Rxjava,其实它又一个最重要的特性,它可以让数据的流向更加直观,代码更清晰

举个栗子

  • 比如说一个庞大的项目,一个事件传递的整个过程可能要经历很多方法,方法套方法,每个方法的位置七零八落,一个个方法跳进去看,跳过去跳过来很容易把脑袋弄晕,不够直观,但是Rxjava可以把所有逻辑用链式加闭包的方式呈现,做了哪些操作,谁在前谁在后非常直观,逻辑清晰,维护就会非常轻松,就算不是你写的你也可以很快的了解,你可以把它看作一条河流,整个过程就是对里面的水流做进行加工,懂了这个特性我们才知道在复杂的逻辑中运用Rxjava是多么的重要

结语

  • 学习新技术,我们不应该盲目的跟风,我们如果不知道这个技术为什么出现,出现是为了解决什么,我也就不知道为什么运用它,我们就算在项目中使用也无法灵活运用,非常浅显的使用,复制粘贴一些模版代码,也根本无法扩展自己的思维

  • 这些技术虽然比较适合大项目一点,但是还是建议各位开发者开始使用他们,使用他们能扩展自己的思维,让自己考虑耦合,扩展,团队协作之类大项目才会考虑的问题,你如果一直重复的按最简单的方式写项目,什么都不考虑,你就算是5年经验,也只是以第一年的经验重复5年

  • 最后介绍一个将MVP,Dagger,Retrofit,Rxjava等技术相结合并用于快速开发的框架,如果想搭建一个新项目使用这些技术,改了包名就可以直接使用,包含详细的文档,相比于这些技术漫长的学习曲线,我们在实践中学习他们不是更快吗?后面我会写一篇文章,介绍它是怎么将MVP,Dagger相结合并使用到项目中的

Where?

MVPArms一个Mvp快速搭建框架,欢迎你的Star和Issues

MVPArms MVP快速集成框架

Logo

前言

  • 今年的Android技术圈中MVP,Dagger2,Rxjava,Retrofit这些词汇非常火,随便打开一个技术论坛都充斥着大量的关于这些技术的文章,Github也充斥着各种以基于MVP+Retrofit+RxJava+Dagger2+MaterialDesign开发的xxxx为标题的开源项目或Demo.

  • 但是大家这么热心的开源此类项目,一直重复的做着同样的事教授大家使用的方式和技巧有没有想过依赖一个第三方库,就可以快速的搭建此类框架?

What is MVPArms?

  • MVPArms是一个集成了大量Android主流框架,并且全部使用Dagger2管理,以及提供API将所有库连接起来方便使用,还提供详细的Wiki文档.

  • 它可以使开发后面的所有项目都不用重复的复制粘贴(用过此类框架的朋友应该知道,这些库都依赖其它的库,就算一个build.gradle都会浪费很多时间),一个依赖省去很多烦恼,而且对于新手来说这些框架难的不仅仅是API的使用,更难的是怎么把它们结合到一起,应对各种场景的使用.

  • 对于一个新的Android项目,特别是熟练使用Dagger2Rxjava的开发者,你们只需要将此项目Clone下来,Demo只实现了一个页面,将此页面删除掉,添加所需要的Retrofit API,你的框架就搭建好了,你就可以直接使用Demo进行后续的开发,包结构也适合后面的扩展.

Notice

扩展项目, 了解一下:

Feature

  • 通用框架, 适合所有类型的项目, 支持大型项目的开发, 兼容组件化开发, 可作为组件化的 Base

  • Base 基类(BaseActivity, BaseFragment, BaseApplication …)
  • MVP 基类(IModel, IVIew, IPresenter …)
  • 框架高度可自定义化 (ConfigModule), 可在不修改框架源码的情况下对 Retoift, Okhttp, RxCache, Gson 等框架的特有属性进行自定义化配置, 可在不修改框架源码的情况下向 BaseApplication, BaseActivity, BaseFragment 的对应生命周期中插入任意代码, 并且框架独有的 ConfigModule 配置类, 可在不修改框架源码的情况下为框架轻松扩展任何新增功能
  • 独创的 RxLifeCycle 应用方式, 可在不继承 RxLifeCycle 提供的 ActivityFragment 的情况下, 正常使用 RxLifeCycle 的所有功能, 且使用方式不变
  • 独创的建造者模式 Module (GlobalConfigModule), 可实现使用 Dagger2 向框架任意位置注入自定义参数, 可轻松扩展任意自定义参数
  • 全局使用 Dagger2 管理 (将所有模块使用 Dagger2 连接起来, 绝不是简单的使用)
  • 全局监听整个 App 所有 Activity 以及 Fragment 的生命周期 (包括三方库), 并可向其生命周期内插入任意代码
  • 全局监听 Http Request(请求参数, Headers …), Response (服务器返回的结果, Headers, 耗时 …)等信息(包括 Glide 的请求), 可解析 json 后根据状态码做相应的全局操作以及数据加密, Cookie 管理等操作
  • 全局管理所有 Activity (包括三方库的 Activity), 可实现在整个 App 任意位置, 退出所有 Activity, 以及拿到前台 Activity 做相应的操作(如您可以在 App 任何位置做弹出 Dialog 的操作)
  • 全局 Rxjava 错误处理, 错误后自动重试, 捕捉整个应用的所有错误
  • 全局 UI 自适应
  • 图片加载类 ImageLoader 使用策略模式和建造者模式, 轻松切换图片加载框架, 方便功能扩展
  • 网络请求日志打印封装(提供解析后的服务器的请求信息和服务器的响应信息, 按可自定义的任意格式输出打印日志, 内置一个漂亮的打印格式模板)
  • 框架内自有组件的缓存机制封装(框架内可缓存内容的组件都提供有接口供外部开发者自定义缓存机制)
  • 代码生成插件(MVPArms 全家桶一键生成所需要的所有类文件)
  • Demo 修改包名后就可以直接使用, 快速接入(老项目接入请按下面的步骤)

Where?

MVPArms欢迎StarFork

Architectural

Package Structure

How?

Wiki

详细用法请参照Wiki,下面只是简单的介绍下MVP

Contract

根据Google官方的MVP项目,可以在Contract中定义MVP的接口,便于管理,此框架使用Dagger注入Presenter无需定义Presenter接口,所以Contract只定义ModelView的接口

public interface UserContract {
	//对于经常使用的关于UI的方法可以定义到BaseView中,如显示隐藏进度条,和显示文字消息
    interface View extends BaseView {
        void setAdapter(DefaultAdapter adapter);
        void startLoadMore();
        void endLoadMore();
    }
	//Model层定义接口,外部只需关心model返回的数据,无需关心内部细节,及是否使用缓存
    interface Model {
        Observable<List<User>> getUsers(int lastIdQueried, boolean update);
    }
}

View

一般让ActivityFragment实现Contract中定义的View接口,供Presenter调用对应方法操作UI,BaseActivity默认注入Presenter,如想使用Presenter,必须指定Presenter的范型,和实现setupActivityComponent来提供Presenter需要的ComponentModule

public class UserActivity extends WEActivity<UserPresenter> implements UserContract.View {

    @Override
    protected void setupActivityComponent(AppComponent appComponent) {
        DaggerUserComponent
                .builder()
                .appComponent(appComponent)
                .userModule(new UserModule(this))
                .build()
                .inject(this);

    }

    @Override
    protected View initView() {
        return LayoutInflater.from(this).inflate(R.layout.activity_user, null, false);
    }

    @Override
    protected void initData() {
       }
}

Model

Model实现ContractModel接口,并且继承BaseModel,指定范型为ServiceManagerCacheManager,然后通过两个Manager拿到需要的ServiceCachePresenter提供需要的数据(是否使用缓存请自行选择,Presenter无需关心细节)

public class UserModel extends BaseModel<ServiceManager,CacheManager> implements UserContract.Model{
    private CommonService mCommonService;
    private CommonCache mCommonCache;

    public UserModel(ServiceManager serviceManager, CacheManager cacheManager) {
        super(serviceManager, cacheManager);
        this.mCommonService = mServiceManager.getCommonService();
        this.mCommonCache = mCacheManager.getCommonCache();
    }
    
    @Override
    public Observable<List<User>> getUsers(int lastIdQueried, boolean update) {
    
    }
  
}

Presenter

PresenterMVP中的大部分的作用为通过从Model层接口获取数据,在调用View层接口显示数据,首先实现BasePresenter,指定ModelView的范型,注意一定要指定Contract中定义的接口,Presenter需要的ModelView,都使用Dagger2注入,这样即解藕又方便测试,怎么注入?

@ActivityScope
public class UserPresenter extends BasePresenter<UserContract.Model, UserContract.View> {

    @Inject
    public UserPresenter(UserContract.Model model, UserContract.View rootView) {
        super(model, rootView);
    }
    //这里定义业务方法,相应用户的交互
    public void requestUsers(final boolean pullToRefresh) {
    
}

Acknowledgement

感谢本框架所使用到的所有三方库的Author,以及所有为Open Sourece做无私贡献的DeveloperOrganizations,使我们能更好的工作和学习,本人也会将业余时间回报给开源社区

  1. MvpGoogle官方出品的Mvp架构项目,含有多个不同的架构分支(此为Dagger分支).
  2. Dagger2Google根据Square的Dagger1出品的依赖注入框架,通过Apt编译时生成代码,性能优于使用运行时反射技术的依赖注入框架.
  3. Rxjava提供优雅的响应式Api解决异步请求以及事件处理.
  4. RxAndroid为Android提供响应式Api.
  5. Rxlifecycle在Android上使用rxjava都知道的一个坑,就是生命周期的解除订阅,这个框架通过绑定activity和fragment的生命周期完美解决.
  6. RxCache是使用注解为Retrofit加入二级缓存(内存,磁盘)的缓存库.
  7. RxErroHandlerRxjava 的错误处理库,可在出现错误后重试.
  8. RxPermissions用于处理Android运行时权限的响应式库.
  9. RetrofitSquare出品的网络请求库,极大的减少了http请求的代码和步骤.
  10. Okhttp同样Square出品,不多介绍,做Android都应该知道.
  11. Autolayout鸿洋大神的Android全尺寸适配框架.
  12. GsonGoogle官方的Json Convert框架.
  13. ButterknifeJakeWharton大神出品的view注入框架.
  14. Androideventbus一个轻量级使用注解的Eventbus.
  15. TimberJakeWharton大神出品Log框架容器,内部代码极少,但是思想非常不错.
  16. Glide此库为本框架默认封装图片加载库,可参照着例子更改为其他的库,Api和Picasso差不多,缓存机制比Picasso复杂,速度快,适合处理大型图片流,支持gfit,Fresco太大了!,在5.0以下优势很大,5.0以上系统默认使用的内存管理和Fresco类似.
  17. LeakCanarySquare出品的专门用来检测AndroidJava的内存泄漏,通过通知栏提示内存泄漏信息.

Hello 我叫Jessyan,如果您喜欢我的文章,可以在以下平台关注我😘