浅谈安卓项目框架发展
来自: http://blog.csdn.net//guijiaoba/article/details/50223227
浅谈安卓项目框架发展
翻译自Android Application Architecture
Android开发的生态环境变化非常快,每时每刻都会有一些新的库和工具产生。
2012年前
2012年的时候,当时安卓程序的主要框架是,没有什么网络请求库。任何耗时操作都是使用AsyncTasks完成。基本框架图如下所示。
代码中只有2层:数据层、UI层。
- 数据层:使用REST API来请求数据,保存数据,为界面提供数据的支持。
- UI层:显示数据层的数据,同时处理用户的事件。
同时会APIProvider来提供一些接口方法,给Activity或Fragment来调用请求数据,APIProvider内部使用URLConnection结合AsyncTasks的方式,来请求数据。当数据回来后,通过一些列的回调给Activity和Fragment。
CacheProvider用来保存一些缓存数据,如SharedPreferences来保存简单数据,用SQLite来保存复杂的数据,当然CacheProvider也会提供一些回调给UI层。
问题
通过以上的方法来架构程序,会使的UI层很重。比如,程序中有个功能是用ListView来加载图片的场景,同时用sqlite缓存的技术。那么正常情况下,Activity需要做如下的操作。
- 调用APIProvider中loadPosts(callback) 的方法。
- 在回调中等待获取数据成功,然后再调用CacheProvider的savePosts(callback)方法来缓存数据。
- 等待数据保存成功后,然后再把数据显示在ListView中。
- 假如某一步失败了,那么还要在某个回调中单独处理。
这是一个比较简单的例子。在实际的情况下,REST API可能会返回一个复杂的数据,Activity可能需要对数据做一些处理,才能显示。比如其他一些使用场景,要从Play Server SDK中异步加载邮件名称,那么在代码中可能会有回调方法嵌套的问题。如果这种回调嵌套太多,那么对于程序来说,简直是一团糟,一个大坑。
总结
- Activity和Fragment会变得非常庞大,并且难以维护。
- 太多的回调嵌套,不方便未来代码的扩展。
- 不能进行单元测试,有很多的逻辑代码放在UI层,就非常难以测试。
使用RxJava架构
上面的说的程序框架我们使用2年多,当然我们也做了一些修改。比如,我们在APIProvider中使用Volley
来进行网络请求。然后我们的代码就变得非常难以测试,掉进一个回调嵌套的大坑里面。
2014年的时候,我们开始了解到RxJava
,自己也经常写一些小的Demo,发现它可以解决回调嵌套问题。如果你还不了解RxJava,你可以在这里了解到。简单来说,Rxjava可以让你的异步方法变成流一样处理,同时你还可以对流中数据的进行转化、过滤、组合等。
使用Rxjava后,我们的项目结构变成如下所示。
相对于来第一个版本的架构来说,我们对数据层和UI层进行了分离。数据层变成了一个数据管理类(DatManager),数据管理类会持有很多数据帮助类(Helper classes)。UI层就是使用安卓系统提供的组件来显示数据,如Fragment,Activity,ViewGroup等。
数据帮助类(Helper classes)通常是一些第三方的框架和库,用来保存和处理数据,很方便。比如通过REST API接口来获取数据,就可以使用第三方的工具。不同的程序获取数据方式是不同的,但是相同点是:
- PreferencesHelper可以保存和读取SharedPreferences中的数据。
- DatabaseHelper可以访问数据库
- Retrofit Services可以访问web服务器中的数据,我们把Volley替换成Retrofit,因为Retrofit提供RxJava方式的调用接口。
项目中大部分的public方法都变成了RxJava Observables的方式。
DataManager就是整个项目的大脑,它使用Rxjava的方式,从各种帮助类中获取数据,然后对数据进行处理,最后把数据传给界面层,界面层不再需要关心怎么处理数据了,直接用来显示。
比如我们需要一个显示博客内容,整个一个流程如下所:
- 通过REST API来获取一个博客的列表。
- 使用DatabaseHelper来保存获取到的数据。
- 当我们需要现在在界面中过滤显示今日所写的博客时候,就可以使用Rxjava对数据进行过滤。
UI层中组建只需要调用简单调用某个方法,然后会使用Rxjava中Observable来接受数据。或者可以通过适配器模式,来显示在不同的组建中。
最后我们在项目中使用了EventBus。EventBus就像安卓系统的中广播一样,可以随时在数据层发送一个事件,然后界面中的可以有多个组建来接受这个事件。比如我有个退出登录操作,数据层在调用signOUt方法后,发送一个退出登录的事件。那么各种Activity都会受到这个事件,然后对界面上显示的数据进行刷新。
新架构的优点
- RxJava提供统一的Observables和操作,这样可以去除回调嵌套
- DataManager持有多个业务数据的仓库,这样Activity和Fragment只需要负责显示,无需做过多的数据操作。
- 把数据从UI层移动到DataManager中,这样很方便进行单元测试。
- 职责分明,DataManager只需要关注数据的存储和处理,同时使程序变得容易测试。各种帮助类,也很方便的mock数据。
新架构的缺点
- DataManager将变的非常的大,非常难以维护。
- 虽然UI层变得非常简单,只需要负责显示数据。但是它还需要在Rxjava的回调中处理一些其他的业务逻辑。
MVP架构
又过一年左右,有一些新的架构方式出现。比如MVP和MVVM已经在社区变的流行起来。通过几个Demo和文章,我们发现MVP可以对我们现在的架构做出优化。因为当前的架构的只有2层,添加一个MVP很方便自然。添加了MVP后,我们的架构变成了这样。
现在的数据层已经变成了Model,更加清楚明了。
Presenters是把原先在Datamanager中加载数据的方法移动到Presenters中,当界面需要加载数据时候,只需要调用Presenters即可。当然也是采用Rxjava的方式。同时Presenters可以对加载数据错误,进行适当的处理,这样比把所有的数据处理放在DataMangager中要好。
最后发现Presenters中的public方法跟都是使用Rxjava中的调用方式,然后Rxjava在调用DataManager中方法。
MVPView是一个显示接口,用来显示Presenters返回的数据,通常都是Activity、Fragment、ViewGroup来实现这个接口,然后再去显示数据。
相对于第二个版本,我们发现UI层通含就是安卓系统提供的组件,如ViewGroup、Activity、Fragment。主要的不同的是,对不同Observables做不同的处理。
所以可以提供一个通用的数据展示方法,比如showError()
or showProgressIndicator()
。同时界面组件只需要处理一些事件就可以了,比如按钮的点击事件,然后加载数据,显示数据。
MVP资料
优点
- Activity和Fragment变得更加轻量级,只需要处理用户的响应,加载数据,显示数据即可。
- 我们可以很方便的对Presenters进行修改,同时也可以mock些测试数据,这样页面测试也变的很方便。
- 假如Data Manager变的很大,可以把部分代码移动到Presenters中。
问题
- DataManager是一个单例,并且这个单利非常大也很复杂。暂时还没有很好的方法能够解决。
很显然,这不是一个完美的程序架构。实际上,并没有一个好的架构能够解决所有的问题。但是安卓的生态圈一直都在不断的发展,同时我们自己也要不断的探索,使我么你的程序更加健壮和优秀。
我希望你能喜欢这篇文章,同时也想这片文章对你有所益处。如问题,可以联系我。