正文
这里需要注意的是SDK层与基础框架层并不是一成不变的,但它们的变化周期往往是比较长的,一般来说当基础功能不能满足最上层的业务逻辑时,就需要对其做扩展。由于基础框架层的功能模块已经是功能级别的粒度划分,因此扩展往往是模块级别的扩展,通常是新增基础功能框架而不是修改原有基础功能框架,这也符合“开放-闭合”原则。
模块化
至于模块化,对于分层化来说则是更细粒度的划分,即将每一层细分为不同的模块,各功能模块尽可能遵循“高内聚、低耦合”的原则,功能模块之间仅提供必要的交互接口。
业务数据流程设计
由于业务逻辑、数据处理逻辑或网络框架的不同,相信各家应用都有自己的一套数据请求流程。最直接的就是从Activity或Fragment中调用网络请求的方法,然后通过回调将结果返回到Activity或Fragment中,虽然流程最清晰,但这种方式存在几个严重的问题:
-
网络数据直接返回到Activity或Fragment中,后续需要对数据进行解析、过滤、转换、缓存等操作,这些工作将会大大加重Activity或Fragment的负担。
-
Activity或Fragment的代码量猛增,逻辑繁杂(不仅包含了View的逻辑还包含了数据处理的逻辑)
-
从整个应用的角度来看,每个页面甚至每个接口都需要重复上述相同的冗余工作,完全可以抽象出来。
上述设计思路是需要摒弃的,结合自身业务及架构演化,我们没有跟风MVP、MVVM,而是设计了下面一套业务数据请求流程:
首先,视图层通常表现为Activity或Fragment,并由视图层发起数据请求,与上述不同,视图层并不直接跟网络框架打交道,而是先将数据请求发送到数据代理层DataAgent。需要注意到是,视图层与数据代理层之间没有采用直接通信的方式,而是插入了一个消息调度器MessageScheduler中转。这样做的好处是将视图层与数据代理层解耦,视图层无需关注数据代理层的具体实现,有了MessageScheduler,视图层所要做的就是发出一个数据请求的消息而已,然后就可以静静等待一个回复消息,该回复消息会附带最终需要的数据对象,这样在视图层就免除了数据处理的逻辑,拿到结果直接展示到UI上即可。使用这种方式,一般来讲Activity或Fragment三五百行代码即可搞定,UI逻辑或接口逻辑(如一个页面有多个接口)比较复杂的代码量基本也能控制在1000行左右,逻辑非常清爽。
消息调度器将视图层的请求消息转发到数据代理层后,DataAgent解析出数据请求类型DataType(该类型对应着具体数据对象模型)、必要参数(接口参数、是否需要缓存结果、分页页码等),然后再执行具体的操作:
-
如果要取缓存的数据,则DataAgent直接向缓存模块发送请求。缓存的数据可以是初始JSON数据,也可以是解析处理后得到的数据对象Model,可根据具体需求配置。如果从缓存中取到的是JSON,则DataAgent先要解析处理得到对应Model;如果从缓存中取到的是Model,则不做处理,然后将Model封装发回到消息调度器,再由MessageScheduler分发给具体的请求者,如Activity或Fragment。
-
由于Android的数据来源有多种,如果数据来自持久化存储,如SQLite或File等,仍然统一由DataAgent来跟它们通信,获取数据并加工后通过MessageScheduler发回视图层。
-
最常见的是从服务器获取数据,此种场景下,DataAgent将与网络框架交互,将从MessageScheduler中获取的参数提供给网络框架构造请求url。至于网络框架使用Volley或OkHttp或者其他都没关系,网络框架负责向Server请求数据,数据通常以JSON格式返回。DataAgent收到返回的JSON数据后,根据DataType将JSON数据校验后抛给解析器,解析器会将JSON解析为视图层需要的Model。当然数据解析过程可能伴随数据的过滤、转换等逻辑。另外需要注意的是,还需要根据视图层需求对数据进行是否缓存的操作,可选择缓存JSON还是Model。经过一系列操作,得到最终Model后,DataAgent将其通过MessageScheduler发回视图层。
当然,由于数据请求流程是耗时的,因此上述步骤都是走的线程池,这点上图中并未注明。
数据代理层
DataAgent在上文中已简单提及,它的主要作用是对数据的一系列操作,包括实际的数据请求、数据解析处理、数据缓存等逻辑。下图为从服务端接口获取JSON数据并处理的流程: