ARouter中 IProvider 到底是什么

3 阅读4分钟

一、先一句话根本定义

IProvider 就是 ARouter 官方规定的【服务接口父接口】所有想要跨模块暴露功能、对外提供服务的接口,必须继承它

java

运行

public interface IProvider {
    // 生命周期初始化方法
    void init(Context context);
}

它里面就一个空方法 init() ,本身没业务代码,纯粹是一个标记 + 规范

二、为什么继承 IProvider,就能对外提供接口?

1. ARouter 的底层扫描规则(核心原因)

ARouter 在编译期(打包时)会做扫描:

所有实现了 IProvider 子接口的实现类,并且加了 @Route(path="...") 我全部收集起来,存入路由注册表。

也就是说:IProvider = ARouter 识别「服务」的唯一标记

  • 普通接口:ARouter 不认识
  • 继承 IProvider 的接口:ARouter 认定这是对外服务

2. 原理:路由注册表

你每次写

java

运行

@Route(path = "/service/car_api")
public class CarProviderImpl implements ICarProvider {

ARouter 编译器会自动生成代码,把:路径 /service/car_api ↔  CarProviderImpl 实现类

绑定存入路由表

等到你调用:

java

运行

ARouter.getInstance().build("/service/car_api").navigation();

ARouter 就去查表 → 找到实现类 → 创建单例对象 返回给你。

3. 为什么非要继承 IProvider?不能直接用普通接口?

如果没有 IProvider

  • ARouter 分不清你这个类是跳转页面、还是普通工具类、还是服务
  • 无法统一管理单例、无法统一初始化、无法统一生命周期
  • 无法做组件化解耦

IProvider 就是一个身份牌

拿到这个身份牌 = 我是对外服务,可以跨模块调用

三、完整一套结构(你项目 1:1 对应)

1. 顶层父接口(ARouter 自带)

java

运行

public interface IProvider {
    // 服务初始化时回调,框架自动调用
    void init(Context context);
}

2. 业务子接口(暴露对外方法,放在 base 公共模块)

java

运行

// 车机服务接口,所有模块都能依赖 base,但是不依赖车机模块
public interface ICarProvider extends IProvider {

    // 对外提供:监听Tab切换
    LiveData<Pair<Integer, Object>> getCarTab();

    // 对外提供:切换Tab
    void switchTab(int index);
}

3. 接口实现类(在车机业务模块内部,不对外暴露)

java

运行

// 只有车机模块自己知道这个实现类
@Route(path = RouterCarPath.Provider.CAR_API)
public class CarProviderImpl implements ICarProvider {

    @Override
    public void init(Context context) {
        // 框架自动初始化,你不用管
    }

    @Override
    public LiveData<Pair<Integer, Object>> getCarTab() {
        // 真实业务逻辑
        return carTabLiveData;
    }
}

4. 其他模块调用(完全不依赖车机模块)

java

运行

ICarProvider carProvider = (ICarProvider) ARouter.getInstance()
        .build(RouterCarPath.Provider.CAR_API)
        .navigation();

// 直接调用方法,监听Tab
carProvider.getCarTab().observe(xxx);

四、IProvider 到底实现了什么能力?(4 大核心作用)

1. 组件化完全解耦(最重要)

  • A 模块要用 B 模块功能
  • A 完全不用依赖 B 的 module
  • 只依赖 base 里的接口 ICarProvider
  • 实现类藏在 B 模块内部,外部完全看不见

这就是大厂组件化架构的核心。

2. 全局单例

ARouter 拿到的 Provider 默认全局单例整个 App 只有一个实例,不用你自己写单例、不用 Dagger、不用 Hilt。

3. 统一初始化生命周期

所有 Provider 的 init(Context) 方法App 启动时 ARouter 自动调用你不用在 Application、不用在 StartUpTask 手动初始化。

4. 统一服务管理

所有跨模块能力全部收拢到 Provider

跳转页面用 @Route

调用功能服务 全部用 IProvider

五、你最疑惑的灵魂问题:

为什么它就可以对外提供接口?

我用大白话总结成 3 句你永远忘不掉:

  1. IProvider 是 ARouter 官方规定的【服务标识接口】
  • 只要接口继承它,ARouter 就认定这是对外服务。
  1. 配合 @Route 注解,编译期自动生成路由映射表
  • 路径实现类绑定,外部只需要填路径就能拿到对象。
  1. 接口在公共基础层,实现在业务内层
  • 外部只看得见接口,看不见实现,完美解耦,实现跨模块调用。

六、结合你刚刚的代码完整串讲

java

运行

// 1. 根据路径查表,拿到车机服务的单例实例
ICarProvider carProvider = (ICarProvider) ARouter.getInstance()
        .build(RouterCarPath.Provider.CAR_API)
        .navigation();

// 2. 调用接口里暴露的方法,拿到可观察的Tab事件
// 因为ICarProvider继承了IProvider,所以才能被ARouter获取到
carProvider.getCarTab()
        // 3. 生命周期安全监听
        .observe(container.getViewLifecycleOwner(), pair -> {
            // Tab切换回调
        });

七、和你之前所有知识点串联(全部打通)

  1. @StartUpTask:App 启动自动初始化各个 SDK
  2. IProvider:模块之间对外暴露服务、跨模块拿对象
  3. Consumer<Fragment> :Fragment 创建完成回调任务
  4. Navigation 动态注册:拿到服务后动态添加页面、动态跳转
  5. LiveData.observe:监听服务内的数据变化(Tab 切换)
  6. Maybe:获取服务有可能为空、异常的场景封装

八、终极精简背诵版(面试直接说)

  1. IProvider 是 ARouter 服务接口的父接口,仅作为标记规范

  2. 子接口继承它 + 实现类加 @Route,即可被 ARouter 注册为服务

  3. 外部模块通过路径 navigation() 即可获取实例,无需模块依赖

  4. 作用:组件化解耦、跨模块功能调用、全局单例、统一初始化

  5. 区别:

    • @Route 用于 页面跳转 (Fragment/Activity)
    • IProvider 用于 功能服务调用 (方法)