iOS 开发 将来跳槽用iOS学习专题

组件化实践详解(一)

2018-03-21  本文已影响1861人  未来的理想

1、目标

本文主要记录组件化项目的实践过程及其中的思考。

具体实施一项技术项目之前我们会首先确定对应的目标,之后的行动计划都会朝着目标一步步靠拢。

简单的总结就是把一个大的Project工程,变成若干个小的Module工程,就是这样。

组件化前后变化

看到这个图大家是不是想你要说的原来这么简单啊,先把刀都放下好好说话,实际上组件化看起来简单但是实践道路确是异常艰难,不信我们继续看!

2、基础库抽取

最初我们的Project整体只有一个Module,也就是说业务代码和技术代码都在一起,通过package的方式区分开来的。这种情况下做组件化难度是极大的,注意不夸张的说就是极大,因为大家在一起紧紧的抱成一团,相互依赖,然而要想直接拆出来困难重重:首先要把所有的基础库抽取出来到单独的基础Library工程,然后App这个Module依赖于这个基础Library工程,发现以下难题:

  1. 基础库可能不按规范不在特定的package下;
  2. 基础库可能和特定业务结合的相对紧密,无法直接移动;
  3. 移动基础库到单独的Library使用AS工具可能移动不完整;
  4. 一个类可能引用了若干个类,几层引用下来,工作量远超想象;

因此当我刚刚迈出第一步的时候我的内心就已经是这样的:

安慰自己万事开头难嘛,我做了以下事情:

  1. 先收集、移动各个不在特定package的基础类到特定package;
  2. 将基础库和特定业务隔离;
  3. 整理、精简基础类;

然后我就开始小心翼翼移动基础类到单独的基础Library,这个过程也十分虐心,因为利用AS的Move功能并不一定保险,强烈建议

这样你就以为解决了所有问题?Naive!!

当时我的表情是这样的:

实在难以一次Move完毕,于是我换了一种思路:Move基础库的原因是为了让新建的别的业务Module使用,也就是Library中必须存在这些基础类,那我直接在Library中创建出来不就行了吗?

对于难以移出的基础类我们项目确实是这么做的,效率明显更高!

3、路由的设计

3.1 为什么需要路由

明确一个问题:各个业务模块之间不会是相互隔离而是必然存在一些交互的;

这两种调用形式大家很容易明白,正常开发中大家也是毫不犹豫的调用。但是我们在组件化开发的时候却有很大的问题:

由此:必然一种支持组件化的交互方式,这种交互方式需要支持UI跳转以及方法调用的能力,同时处理好多参数及不同参数类型。

3.2 方式之使用事件通知

备注:此处事件通知指代EventBus或者广播。

这种思路很好想到,在需要交互的地方发通知,然后接收方根据不同的通知类型做出不同的处理。相信各位老司机不需要代码也能直接明白。

优点:

缺点:

备注:EventBus只有当业务模块在真实的线上运行阶段是在自己单独的进程才不可用,而这种场景对绝大数App完全够用

推荐星级:二星级

3.3 方式之一个固定的方法

实现方案:在Activity或者需要暴露的普通类中声明一个统一的方法,这个方法自己去实现,对Activity来说是去实现UI跳转;对普通类来说则是去实现功能调用。但是这种方式需要解决两个问题:

  1. 对于跨Module类引用不到:首先需要确认的是跨Module的类肯定是引用不到的,那么我们就给这些类打上标记,间接的就能知道相应的类;标记的形式可以是一个Url,对于Url肯定是不区分Module的。例如:我给ActivityA打上一个标记"activitya",然后把这个url作为key,这个类Class作为value使用HashMap存储起来,那么我在别的Module就能直接通过相应的url来获取想要调用的类,然后调用这个特定的方法即可
  2. 方法签名不固定的问题:这个很好理解,我要做不同的事情那需要的参数不管是个数还是类型肯定是不一样的,但是这样的话显然无法做到调用一个固定的方法。这时候我们仍然可以选择曲线救国:我们只传递一个参数进去,而这个参数则是一个HashMap,好处则是,可以传递任意个数、类型的参数。这样调用方法的时候你可以将随意多个数、类型的参数传递进去,然后在方法内从HashMap中取出真正需要的参数

缺点:

推荐星级:强烈不推荐,经得起时间检验的方案才是可行的好方案,而这种方式是经不起规模化推广考验的。

3.4 方式之真正的路由

以上两种方式虽然都可以解决问题,但是坦白讲,如果实际用到了项目里的话推进会是极为困难的一件事,因为体验实在是太差了!一个容易被推进、使用体验好的路由应该具备使用方便、上手成本低,改造成本小等基本素质,那么分摊下来应该具体体现在这几点上:

来看下实际的解决方案:

  1. 对于Activity,我们也是给它打上一个标记,一个Activity对应一个Url,然后处理好参数的传递问题即可
  2. 对于Module间调用,我们在Library工程中创建出每个Module需要向外提供能力的接口,然后每个Module自己去实现对应的实现类;并且也使用HashMap将这个接口与实现类进行保存,这样在别的Module就可以根据在Library中存在的接口获取到真正的实现类,而方法调用的时候就是简单的调用一个对象的方法,IDE提示很友好,而且不限制方法签名哦

推荐星级:强烈推荐!!备注:具体的路由实现之后会有专门的文章

4、业务组件的剥离

在路由的侵入达到一定程度之后就要做业务组件的剥离,需要注意几点:

4.1 先决条件

  1. Library库抽离或者准备完毕
  2. 路由框架侵入要靠前

这两项属于基础设施,不能边开展边做业务组件的剥离,不然一定会万分痛苦:各种报错,各种Build不过影响工作。

4.2 业务剥离的准则

首先需要明确对于不同的项目、要求以及不同的资源分配,业务剥离的程度也是不一样的。

4.3 共享数据的组件

业务组件实现单独运行是可以的,但是实际上很多情况下自己独立运行是跑不起来的,举个例子:大多数业务都会和用户体系挂钩,那么缺乏用户体系的业务组件寸步难行

那么比较好的做法就是在技术组件剥离之后,优先把共享数据的组件(例如用户组件)先剥离出来,然后别的组件需要共享数据的时候就可以直接依赖于这个组件即可

再写下去,本文篇幅就过长不利于吸收了,别的主题我们下篇文章接着聊!

欢迎关注
上一篇下一篇

猜你喜欢

热点阅读