爱奇艺组件化技术探索与项目实践(1)

· 解决多端代码维护问题

根据业务特点,横向和纵向划分组件,以组件为单位承接迭代需求,各端进行组件复用;

· 解决跨组件调用和组件间路由的问题

业务划分更加清晰、组件间解耦更加彻底、组件间通信更高效,对原有业务模块进行抽离和整合,明确组件间的业务边界;

· 提升开发效率,方便开发调试

组件可以单独编译和调试,使模块开发者更聚焦本模块业务;

· 提升集成和提测效率

各端项目需要哪个组件,可以直接通过工具快速集成和提测。

基于以上目标,我们设计了适合爱奇艺知识业务的组件划分策略,下图为组件化之后的功能架构图,横向分为基础组件、功能组件和业务组件,纵向对每个层级的组件又进行细分;从划分粒度上看,组件不仅包括功能性的sdk,还可能包括业务UI,宗旨就是业务模块独立,边界清晰,方便扩展和维护。

二、整体技术架构

====================================================================

基于功能架构,知识组件化的技术架构如下图所示。

最下层是基础组件,包括baselib和componentService,我们将网络库、pingback、数据库、日志和工具类等公共底层实现构成基础组件,屏蔽了系统和各端的差异,位于功能和业务组件的下层。所有功能和业务组件都使用同一套基础组件,可以保证公共部分的统一性。基础组件比较稳定,不会频繁迭代。

再往上一层是功能组件,如承载播放能力的播放器和历史记录组件、承载支付能力的支付和营销组件,、承载多端定制化分享能力的分享&海报组件等各个端都有的基础功能,功能组件位于基础组件和业务组件之间,功能组件会根据业务组件的需要而不断迭代升级。

接下来是业务组件,这层是各个端有可能包含也有可能不包含核心业务模块,为了开发和维护方便,我们将核心业务模块抽取为业务组件,如搜索、筛选、发现feed流、评论、评价、作业作品等,业务组件位于基础组件和功能组件的上层,迭代较频繁,但业务本身比较独立,边界清晰。

最上层是壳工程,各端都需要一个主工程负责集成所需要的组件,我们统称为壳工程,壳工程包括了各端的基础框架,比如组件注册和初始化逻辑,平台相关性处理逻辑等,还有各端特有的业务模块,不适合抽离和拆解的部分。

右侧是负责管理组件间交互和跳转的MoudleRouter和UIRouter。这部分是公共基础设施,各端都要集成。

左侧是构建系统,它不在组件化代码中,属于辅助系统,负责组件和各端应用包的构建。

三、核心技术实现

====================================================================

组件化实践中比较核心的两个技术点是,组件间交互和组件间路由。

3.1组件交互


组件间交互的难点是降低组件耦合度,最好能达到完全无侵入式的调用。经过调研,iOS端使用ModuleManager的方式,它被定义为最底层的服务组件,每个组件都需要对外提供被调用的服务接口,接口的定义存在于ModuleManager组件。ModuleManager的代码对其他组件代码来说是无侵入的,只负责对传递过来的数据进行解析,并将调用消息传递给对应组件。

为了解决URL硬编码 ,以及字典参数类型不明确等问题,iOS端在组件化方案中选用了Protocol方案,在程序开始运行时将自身的Class注册到ModuleManager中,并将Protocol反射为字符串当做key,Class遵守协议并实现协议定义的方法,外界通过Protocol获取的Class并实例化为对象,调用服务方实现的协议方法。独立APP和各个插件的服务注册的时机不同,独立APP是在程序启动时,而插件则是外部调用插件时,在插件退出时去需要解除注册释放资源。Protocol方案描述如下:

在Android端,组件间交互使用的是ZRouter组件,实现思路和iOS端类似,是参考了java中SPI机制(服务提供发现机制),每个组件对外提供一个服务接口service,接口的实现交给对应组件内。在组件初始化注册时候,会同时注册该service接口和对应service实现。业务方使用时,只需要通过service接口调用组件功能。这样组件间就没有了直接依赖关系,实现了组件间解耦隔离。具体调用如下图所示:

3.2组件路由


组件间路由跳转方面,iOS端采用了注册URL的方式,注册的时机分为静态、动态和懒加载三种,懒加载方式即为在调用跳转方法时检查URL与ClassName是否已经注册绑定,如果未绑定则从模块静态信息表中获取并完成注册绑定,Handler可以在动态注册时进行指定,这样跳转逻辑即可实现完全自定义而不走底层的统一跳转逻辑,同样要注意的是插件端需要在退出插件时释放资源并取消注册。

Android端针对组件间UI跳转的实现方面,虽然前面讲到的ZRouter也能做到Activity、Fragment、View之间跳转,但是代码实现过于复杂。所以我们借鉴了业内组件化的优秀思想,专门开发了一个用于组件间UI跳转的UIRouter。在编译期间,通过Activity上添加的@RouterPath注解,生成一张Key为Scheme或页面短码,Value为Activity的路由表。跳转任何一个Activity都交由路由框架,根据路由表决定启动哪个Activity。

为了提升开发效率,减少UIRouter初始化时重复开发的代码,我们开发了一个插入自动注册代码的gradle插件,利用此插件在编译期通过ASM向指定方法中注入初始化代码。

同时,在组件库注册的时候也有用到这个技术;组件初始化类在debug模式下通过反射加入内存,在release模式下则通过ASM插入注册代码。这样在debug模式下可以缩短编译时间提升开发效率,在release正式包中运行时可减少反射带来的消耗。

整个优化流程如下:

四、构建系统

==================================================================

有了层次清晰的组件划分,那么如何快速构建组件和项目成了必需要解决的事情。针对组件化,爱奇艺知识团队结合公司已有的构建系统,开发了一套适用于组件化的快速构建子系统。

为了解决多端共用一套代码和在各个插件端都有包大小的限制的前提下,在组件库中存在的差异代码通过宏分割来控制,实现差异代码隔离,编译时仅编译当前指定的某一端代码,打包时通过指定打包参数来设置宏配置,完成指定端的构建。

iOS端每个组件都是一个单独的工程,由不同的git私有仓库来管理,各个组件是在主项目中通过CocoaPods来集成,将所有组件当做二方库集成到主项目中。爱奇艺知识APP与各端插件虽然都采用了Cocoapods集成的方案,但是在版本依赖上有所差异,为提升开发效率,知识APP作为独立应用程序直接采用了指定git仓库tag号的方式来依赖组件库,插件则需要通过插件库的podsec设置依赖来集成组件库的,这就需要将组件库打成二进制的库文件上传到云,并上传组件库的podspec到私有库中。iOS插件端在主项目中集成组件主要分为两种方式分为源码和framework,在开发调试阶段采用源码方式,可以直接修改代码完成需求开发,在打包提测和发布时采用生成framework,可以加快编译速度不会对外暴露源码。

iOS端选择Jenkins作为构建系统,在组件化初始阶段,我们组件的构建是通过先构建最基础的组件,然后再构建上层组件来完成的整体构建,随着组件库数量增多,依赖关系变复杂之后手动逐一触发构建成为了构建过程的痛点,于是开始进行构建优化,引入了Jenkins的ParameterizedTrigger插件并配合shell脚本使用,使得我们支持组件的单个构建的同时,在主项目构建时支持触发多个组件,组件单独构建时也支持配置依赖构建的项目,实现了一次触发完成全部组件的构建。

组件库构建时会对当前迭代分支的代码进行更新检查,如果存在更新则会构建组件库,不存在更新则直接跳过此次构建。随着端的增加构建系统支持了多端构建,iPhone插件和iPad插件为不同的插件Job,通过脚本实现端的区分完成构建。建系统还实现了版本自增和定时构建,每一次构建完成后都会更新podspec文件中的版本号,在下一次构建时如果未手动指定构建版本便会获取之前的版本进行加一实现版本自增。构建系统对接了企业内部的即时通讯工具,在构建完成后发送通知给已经订阅的用户。下图描述了组件构建流程:

在Android端,同样每一个业务组件都是一个完整的个体,可以当作独立的App来运行,需要满足单独运行及测试的要求,这样可以提升编译速度和开发效率。

目前业界常规做法是每一个组件就是一个工程,由build.properties中一个常量控制区分不同场景,且在build.gradle中sourceSets设置单独调试组件时的配置,区别于发布组件aar时候的独立运行时的配置;

但是这种方案对于爱奇艺知识客户端来说并不完全适用,因为我们组件化最主要的一个目的是要达到多端组件复用,这样也会存在需要进行多端适配情况,每一个端的基础配置信息、基础UI样式等都有所不同,不可能在每一个新的组件工程中都配置一遍。所以,直接使用原本混沌工程的壳工程作为组件调试的Project,将runalone文件夹设置在各自壳工程中,在根目录build.properties中通过常量isModuleType控制编译模式,动态加载测试所需组件依赖,这样就可以在各个环境中单独测试组件了。

此时的组件单独调试模式其实等价于理想状态下的组件化壳工程模式:只有少量配置相关代码、无其他组件无关页面逻辑、动态按需加载组件。

在壳工程根目录gradle.properties中包含各种常量,包括端控制、组件库版本号、编译环境控制、运行时依赖控制和运行模式控制参数等。


自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

结尾

最后,针对上面谈的内容,给大家推荐一个Android资料,应该对大家有用。

首先是一个知识清单:(对于现在的Android及移动互联网来说,我们需要掌握的技术)

泛型原理丶反射原理丶Java虚拟机原理丶线程池原理丶
注解原理丶注解原理丶序列化
Activity知识体系(Activity的生命周期丶Activity的任务栈丶Activity的启动模式丶View源码丶Fragment内核相关丶service原理等)
代码框架结构优化(数据结构丶排序算法丶设计模式)
APP性能优化(用户体验优化丶适配丶代码调优)
热修复丶热升级丶Hook技术丶IOC架构设计
NDK(c编程丶C++丶JNI丶LINUX)
如何提高开发效率?
MVC丶MVP丶MVVM
微信小程序
Hybrid
Flutter

接下来是资料清单:(敲黑板!!!


1.数据结构和算法

2.设计模式

3.全套体系化高级架构视频;七大主流技术模块,视频+源码+笔记

4.面试专题资料包(怎么能少了一份全面的面试题总结呢~)

不论遇到什么困难,都不应该成为我们放弃的理由!共勉~

如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

片转存中…(img-zDFJ56KC-1713685043228)]

不论遇到什么困难,都不应该成为我们放弃的理由!共勉~

如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。

[外链图片转存中…(img-rQEaZfp4-1713685043229)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值