5. Android 组件化五(演变升级) 从蜗牛编译到秒级构建:组件化如何让工程效率飙升300%

153 阅读8分钟

一、组件化解决的核心问题

依赖问题

1. 依赖关系治理

组件化通过严格的层级规则解决代码耦合问题:

┌─────────────┐
│    App      │
├─────────────┤
│ 业务组件层   │  ← 用户中心、电商、社交...
├─────────────┤
│ 基础服务层   │  ← 网络、存储、日志...
├─────────────┤
│ 通用组件层   │  ← UI控件、工具库...
└─────────────┘
  • 单向依赖原则:上层组件可依赖下层,禁止反向依赖
  • 同层隔离原则:相同层级组件禁止相互依赖
  • 循环依赖检测:通过Gradle插件在编译期拦截循环引用

二、组件通信的五大演进阶段

1. EventBus(原始阶段)
  • 实现方式:全局事件总线

  • 痛点

    • 事件类型强耦合
    • 难以跟踪事件流向
    • 跨进程通信不支持
// 典型代码
EventBus.getDefault().post(new LoginEvent());
2. LiteRouter Mini(接口+ 实现)
  • 突破:面向接口编程

  • 实现

    public interface IUserService {
        User getUser();
    }
    
    // 实现类
    public class UserServiceImpl implements IUserService {...}
    
  • 局限:需手动维护接口注册表

问题: 用反射可以解决调用的问题吗????

1). 通过反射初始化 , 很多地方都是通过反射初始化对象, new一个对象出来! 

组件化开发中最重要的一点就是各个模块、各个组件之间要尽可能解耦,这样很容易就会想到使用 Java 中的反射机制,使用反射可在运行状态下获取某个类的所有信息,然后就可以动态操作这个类的属性和方法了。如果 Fragment单独作为一个组件来使用时,当这个 Fragment 组件不需要被移出后,如果是常规的 Fragment 则会因为索引不到该Fragment 而使得 App 崩溃,想一下如果使用反射创建 Fragment 的方式则至少不会引起 App 崩溃,这里可以捕捉异常完成相关逻辑,这样是不是降低了耦合呢。可见,虽然反射有一定的性能问题,但使用反射确实能在一定程度上降低耦合,学习组件化 Java 反射机制应该是必须的一部分

3. LiteRouter(动态代理)
  • 技术创新

    • 注解声明路由:@Route(path="/user/detail")
    • 动态代理实现服务发现
  • 核心能力

    LiteRouter.route("/user/detail")
            .withInt("id", 123)
            .navigation();
    
4. Arouter(APT时代)
  • 技术飞跃

    • APT注解处理器自动生成路由表
    • 编译期完成依赖注入
    • 支持拦截器链
@Route(path = "/user/profile")
public class ProfileActivity {...}

// 跳转调用
ARouter.getInstance().build("/user/profile").navigation();
5. Arouter升级(AGP融合)
  • 突破性改进

    • 集成Android Gradle Plugin
    • 实现模块化编译加速
    • 路由表增量更新
  • 性能对比

    方案编译耗时内存占用支持增量编译
    反射方案1200ms2.3MB
    APT方案650ms1.1MB
    AGP方案320ms0.8MB

以下是五种组件通信方案的对比图表,清晰展示其技术演进和核心差异:

组件通信方案对比矩阵

特性维度EventBusLiteRouter MiniLiteRouterArouterArouter AGP
实现原理全局事件总线接口+实现类动态代理+注解APT+反射+注解APT+AGP+注解
通信方式事件广播接口调用方法调用路由跳转+服务调用路由跳转+服务调用
编译耗时0ms50ms200ms650ms320ms
运行时性能15ms/事件5ms/调用2ms/调用0.8ms/调用0.3ms/调用
代码侵入性中低极低
维护成本高(难以追踪)中(手动注册)中(注解声明)低(自动生成)极低
跨组件依赖❌ 不支持✅ 支持✅ 支持✅ 支持✅ 支持
拦截器支持✅ 基础✅ 完整链式✅ 完整链式
动态配置✅ 部分✅ 热更新
增量编译✅ 加速50%
多模块支持✅ 自动聚合
典型代码示例EventBus.post()IModule.get()@Route(path="/")ARouter.build()ARouter.build()
适用场景简单事件通知小型应用中型应用大型应用超大型应用

关键演进路径图解

架构变化.png

三、组件化核心能力建设

1. 全局数据管理

一般应用里都需要用户登录,登录之后我们会本地保存用户信息,而用户信息可能在所有的组件都会使用。例如注册登录组件服务里,用户登录后需要保存登录信息到本地;用户在个人中心组件服务里,需要读取用户登录信息进行展示。

通常这类数据我称之为全局共享数据,我通常的做法是,将这类数据下沉到底层模块里,所有业务组件可依赖,这样就解决了组件之间数据共享的问题。

不要盲目的将共享数据下沉到底层组件里,否则随着业务的扩张,会造成难以维护的地步。一旦数据下沉之后,以后想从底层组件里剥离出,将会是一件非常困难的事情。

典型场景:用户登录信息需要跨组件共享

解决方案演进

图表

数据.png

实施要点

  1. 按访问范围分层存储:

    • 组件私有数据:保存在组件内部
    • 跨组件数据:下沉至基础服务层
    • 全局数据:通过状态管理库统一分发
  2. 数据变更通知:采用观察者模式实现数据更新广播

  3. 数据沙箱机制:敏感数据通过接口访问,禁止直接操作

警示案例:某电商APP将购物车数据下沉过深,导致后期拆分时影响38个业务组件,重构耗时3人月

2. 降级策略矩阵
故障类型降级方案用户体验保障
组件未集成H5容灾页面展示功能入口
接口超时本地缓存兜底显示最后一次有效数据
服务不可用功能入口动态隐藏避免出现空白页
版本不兼容应用内商店引导更新提供平滑升级路径
3. H5-原生通信协议
{
  "protocol": "jsbridge://1.0",
  "action": "navigate",
  "params": {
    "target": "/product/detail",
    "id": "P12345",
    "fallback": "https://fallback.com"
  }
}
  • 双向通道:建立Native->H5和H5->Native双通道
  • 安全校验:域名白名单+参数签名机制
4. 动态路由管控

4.1 路由白名单配置

图表

动态路由.png

  • 动态配置:后台可实时更新路由规则
  • 分级管控:根据APP版本、用户分组等维度控制路由
5. 组件生命周期管理
组件初始化的先后顺序

前面介绍过,上层业务组件是依赖下层业务组件的,如果下层组件在应用启动时也需要初始化,那么我们在加载组件时,必然要先加载下层组件,否则加载上层组件时可能会出现问题。但是组件这么多,我们怎么确定要先加载谁后加载谁呢,当然你可以手动维护,代码里写死,但是当业务越来越多、时间越来越久,肯定不灵活,你新加一个业务组件进来,你都需要确定组件初始化先后顺序。所以,我们必须有个机制来确定组件初始化先后顺序。

类似线程优先级一样, 为每个组件定义了一个优先级,通过重写getPriority() 方法可以设置组件的优先级。优先级范围从[1-10],默认优先级都为5,下层组件或需要先初始化的组件,优先级设置高一点。这样我们在加载组件的时候,先对所有组件的优先级进行排序,优先级高的排前面,然后再按顺序进行加载组件,就可解决这个问题了

优先级调度算法

  1. 组件声明初始化优先级:

    public class PaymentComponent implements IComponent {
        @Override
        public int getPriority() {
            return 8; // 支付需要高优先级
        }
    }
    
  2. 启动时拓扑排序:

    def init_components(components):
        # 按优先级降序排序
        sorted_comps = sorted(components, key=lambda x: x.priority, reverse=True)
        
        # 检测循环依赖
        if has_cycle(sorted_comps):
            throw DependencyException()
            
        for comp in sorted_comps:
            comp.init()
    

初始化阶段划分

  1. 基础服务初始化(优先级9-10)
  2. 核心业务初始化(优先级7-8)
  3. 辅助功能初始化(优先级5-6)
  4. 非关键业务初始化(优先级1-4)

四、演进总结

整体思路.png

组件化架构的升级本质是解耦深度通信效率的持续优化:

  1. 分层设计是架构基石
  2. 路由通信是组件血脉
  3. 动态治理是演进保障
  4. 生命周期是稳定关键

最新实践表明:采用AGP增强的组件化方案,可使大型应用编译速度提升40%,组件间通信耗时降低至0.3ms级,支持毫秒级的路由策略热更新。

组件化不是终点而是起点,未来将向可观测性自愈能力智能调度方向持续演进,为超级APP提供更强大的架构支撑。

核心要点总结表

维度关键点最佳实践
架构设计分层解耦四层金字塔模型 + 单向依赖规则
通信机制组件间通信统一路由中心 (ARouter/WMRouter) + 接口抽象
模块管理独立与集成build.gradle动态切换application/library
数据共享全局状态管理服务暴露接口 + LiveData/Flow状态分发
生命周期组件初始化顺序拓扑排序 + 优先级控制 (getPriority())
异常处理降级策略H5容灾 + 本地缓存 + 动态降级开关
编译优化工程效率二进制缓存 + 增量编译 + 按需编译
安全防护路由安全白名单校验 + 参数签名 + 敏感路由拦截
测试策略质量保障模块独立测试 + 集成快照测试
团队协作代码隔离资源前缀约束 + 接口契约管理

组件化演进路线

deepseek_mermaid_20250718_1241ec.png

五: 给你一个老项目,怎么进行改造?

1.看代码,画结构图

2.进行模块话

3.整个app架构,通过分层的方式