序
本文介绍了android应用的开发,经历了两次架构变革,第一次集成了RxJava第二次集成了MVP,并将RxJava与MVP完美结合,实现了低耦合,代码简单,测试方便的架构。
其实我们在开发中也遇到过,Android入门门槛较低,如果前期对APP规划不清,Coder们对未来把我不准,技术架构经验不够强大,最终导致就是一个Activity几千行,里面写了大量的Private方法,拆成几个Fragment、封装出来的几个类都无法解决,结果就是看Activity难受的要死,纠结,看了不爽改也不是,不该也不是,严重影响看得人的心情,并且怨天尤人这个产品规划APP不好,没有前瞻性,改来改去。
这篇文章就是使用新的结构解决该问题。
安卓APP架构
Android Application Architecture
这篇文章主要目的是讲述如何将传统的Activites与AsyncTasks模式项目前主流的MVP架构基础的响应式编码框架过度,
先畅想一下:如果耦合架构,分工明确,然后完美的组合在一起工作是不是很吊的事情,
最近几年Android的生态链变化非常迅速,从底层的Android Api到应用层的各种开元的类库、工具更新非常迅速。一不留声就落后了。
我在Ribot团队从事Android应用开发三年多,伴随着公司技术的不断创新,积累了很多经验、错误以及在技术选项背后的故事。
旧的应用框架
2012年那个时候,我们代码都是用的原生的Android,没有任何的网络请求框架,而是基于AsyncTacks书写,
显示代码分为两层,Data与View,Data层主要是用来从API获取数据,保存到持久化的db当中,View层就是主要把Data的数据显示到Ui上,APIProvider提供的方法,用于在Acitivy或者Fragment中方便的进行控制与交互,在技术上,将使用URLConnecction与AsycnTasks实现一个异步的网络请求并将结果返回到调用的方法里面。
相同原理CacheProvider提供一系列方法,将SharePreferences或者SQLite的数据提取出来,并且返回给Activity
主要问题是View层有太多的累赘,以一个博客列表为例讲述,比如博客需要显示一个ListView,从SQLite读取数据,
Activity需要做到以下几点:
1.执行APIProvider里面的loadPosts的方法,里面传入回调参数内容,
2.等待loadPosts执行成功以后,执行回调里面CacheProvider中的savePosts方法,savePosts也要传入回调参数,
3.等待savePosts执行成功后,执行回调里面的方法刷新ListView
4.分别书写代码处理2 3两步错误回调内容。
这还是一个比较简单的一个例子,在一些真是的场景中,远程的API可能还没有返回程序的必须值,但是Acitvity必须把数据处理完成功之后才能显示结果,再一个例子就是如果loadPosts方法需要借助一些其他地方返回参数时,类似用多线程去实现同步请求,为保证数据的正常请求,意味着必须做一个三层的回调,如果再复杂一些,想理解清楚这些回调就是很蛋疼的一些事情。
总之,回调多了之后,Activity与Fragment会乱,并且一般人无法直视。
牛逼的架构出来了
我们在蛋疼的架构中煎熬了2年,当然也尝试过很多方式,最终也只能是缓和一下乱的问题,我们在APIProvider中使用了Volley,代替了AsyncHttpClient,但是趋势是一个吊样。
不到2014年我们就开始进行Rxjava的预研,然后尝试了一批简单的项目,感觉Rxjava的方式是解决我们嵌套回调的终极解决办法。简单的说,RxJava允许你通过异步流的方式管理的数据,并且可以通过操作符(Operators)对Observable对象的变换
我们用了几年的经验痛定思痛,搞了下面这个东西,新的APP架构图
与第一种方法相似,这个架构也是分为Data层与View层,Data层饱汉DataManager与一堆Helper;View层是饱汉Fragments,Activities,ViewGroup等。
Helper主要是集成第三方的类库,以便于在代码中几行代码可以清晰的实现某个功能,比如请求API,访问数据库等,虽然不同的应用程序有不同的类库,但是他们无非就是一下内容:
从SharePreferences中读取或者写入数据
读写SQLite数据库
类似于square的Retrofit服务,也就是Http Client,我们用Restrofit替代了Volley以为他们支持Rxjava,并且更吊。
Rxjava最核心的两个东西是Observables(被观察者,事件源)和Subscribers(观察者),在Helper类中的Public方法,一般都会返回一个Rxjava的Observable对Helper返回的数据进行的整合过滤、二次处理
下面举个例子来说明DataManager是做什么的;
1.调用Retrofit的服务,去盛情一个博客列表的API
2.用DatabaseHelper保存这些数据到数据库
3.过滤出这些BLOG那些事今天写的,然后显示到UI界面上。
Observables发出一系列事件,Subscribers(例如 Activities or Fragments)处理这些事件,可以直接将数据显示到一些可以回收、重用的View上面。
【BTW:如果一个Observerble没有任何的Subscriber,那么这个Observable是不会发出任何时间的】
这个架构的另外一个模块是event bus,event bus 可以让我们在Data层发出广播(不是Android的Broadcast)然后不同的模块去注册并接受不同的广播事件
为什么这个方式这么牛逼,是因为Observables与operators可以去掉那一堆必须的回调方法
DataManager替代了传统代码中很多代码,从而使得Activity与Fragment变得更加轻量级。并且使得单元测试变得更加简单。
DataManager成为了唯一的数据交互部分,这样清晰的架构使得更方便进行代码自测。
我们还有什么为题?
如果对于庞大并且复杂的项目来说,DataManager也会变得非常臃肿并且难以维护。
尽管Activityu与Fragment已经变得更加轻量级,但是对于错误一场的处理还是要再subcriptionsd的地方去书写。
一体化的MVP模式
前几年开始,很多类似MVP于MVVM在Android的一些社区比较流行,经过研究之后我们发现MVP模式是我们目前的方案最有价值的改动,我们的两层架构View-Data与MVP的Model-View架构天然融合,理念一致。我们只需要增加一个persenters层,然后把之前在view实现的代码移到上面就可以了。
之前的Data层就是现在的MVP中的Model,Presenter现在负责从Model中加载数据,加载完成后再去调用左边的Activity、ViewGroup中的方法。Presenters的subscribe去接受data manager中的Observables广播出来的数据。举例说明,如果我们需要增加数据的过滤操作但是并不是所有地方都需要那种,那就可以在presenter里面写这些代码,
而不用卸载公共的datamanager里面。
我们定义的dataManager.loadTodayPosts()会广播出数据给到对应的subscribes
MVP的View并不是指的Android的View,而是一个界面组建的实例,例如Activity,Fragment,ViewGroup在注册presenter的是时候,需要把自己当前的实例传递进去。