移动应用 活跃维护

ARouter

alibaba/ARouter

💪 A framework for assisting in the renovation of Android componentization (帮助 Android App 进行组件化改造的路由框架)

14454
Stars 标星
2601
Forks 分支
366
Watchers 关注
5
Open Issues
Java
主要语言
Apache-2.0
开源协议
26.3 MB
仓库大小
17 天前
最后推送
一键安装扩展 / 插件指令
dsh plugin --profile web add github:alibaba/ARouter
git clone https://github.com/alibaba/ARouter.git
git clone git@github.com:alibaba/ARouter.git
README.md develop

英文原文正文为项目原始 README(英文),本站后续会翻译为中文,当前仅剔除图片与无关章节并统一排版。

    A framework for assisting in the renovation of Android app componentization

中文文档

📷 原文此处有图片,请前往 GitHub 仓库查看完整内容。

最新版本

模块 arouter-api arouter-compiler arouter-register arouter-idea-plugin
版本

📷 原文此处有图片,请前往 GitHub 仓库查看完整内容。
|

📷 原文此处有图片,请前往 GitHub 仓库查看完整内容。
|

📷 原文此处有图片,请前往 GitHub 仓库查看完整内容。
|

📷 原文此处有图片,请前往 GitHub 仓库查看完整内容。

演示

演示 apk、演示 Gif

一、功能

  1. 支持直接解析标准 URL 进行跳转并自动注入参数到目标页面
  2. 支持多模块
  3. 支持拦截器
  4. 支持依赖注入
  5. 支持 InstantRun
  6. 支持 MultiDex
  7. 映射按组分组,多层级管理,按需初始化
  8. 支持用户指定全局降级和局部降级策略
  9. Activity、拦截器和服务可以自动注册到框架中
  10. 支持多种方式配置过渡动画
  11. 支持 Fragment
  12. 全面支持 Kotlin(参考 Other#2)
  13. 生成路由文档支持
  14. 提供 IDE 插件,可快速跳转到目标类
  15. 支持增量注解处理
  16. 支持动态注册路由元数据

二、经典案例

  1. 从外部 URL 转发到内部页面,并解析参数
  2. 多模块之间跳转和解耦
  3. 拦截跳转流程,处理登录、统计等逻辑
  4. 跨模块通信,通过 IoC 解耦组件

三、配置

当前开发线路原生使用 AndroidX。使用它的应用必须启用
android.useAndroidX=true;ARouter 本身不需要 Jetifier。仍然使用传统 Support Library 的项目应保持在 ARouter 1.x 版本,直到应用迁移到 AndroidX。命名空间的更改是源兼容性和二进制兼容性的分界,因此其发布会作为主要版本变更处理。

ARouter 运行时保持 minSdkVersion=14。演示应用及其基于 Gson 的
module-java 使用 minSdkVersion=21;Gson 不是 ARouter 运行时依赖。

  1. 添加依赖和配置

    android {
        defaultConfig {
            ...
            javaCompileOptions {
                annotationProcessorOptions {
                    arguments = [AROUTER_MODULE_NAME: project.getName()]
                }
            }
        }
    }
    
    // Required by the current AndroidX development line.
    // gradle.properties: android.useAndroidX=true
    
    dependencies {
        // Replace with the latest version
        compile 'com.alibaba:arouter-api:?'
        annotationProcessor 'com.alibaba:arouter-compiler:?'
        ...
    }
    // Old version of gradle plugin (< 2.2), You can use apt plugin, look at 'Other#1'
    // Kotlin configuration reference 'Other#2'
  2. 添加注释

    // Add annotations on pages that support routing (required)
    // The path here needs to pay attention to need at least two levels : /xx/xx
    @Route(path = "/test/activity")
    public class YourActivity extend Activity {
        ...
    }

    静态路由路径在一个模块内必须唯一。Route.priority 会被复制到路由元数据中;它不是覆盖规则,也不会在声明相同路径的目标之间进行选择。

  3. 初始化 SDK

    if (isDebug()) {           // These two lines must be written before init, otherwise these configurations will be invalid in the init process
        ARouter.openLog();     // Print log
        ARouter.openDebug();   // Turn on debugging mode (If you are running in InstantRun mode, you must turn on debug mode! Online version needs to be closed, otherwise there is a security risk)
    }
    ARouter.init(mApplication); // As early as possible, it is recommended to initialize in the Application
  4. 启动路由

    // 1. Simple jump within application (Jump via URL in 'Advanced usage')
    ARouter.getInstance().build("/test/activity").navigation();
    
    // 2. Jump with parameters
    ARouter.getInstance().build("/test/1")
                .withLong("key1", 666L)
                .withString("key3", "888")
                .withObject("key4", new Test("Jack", "Rose"))
                .navigation();
  5. 添加混淆规则(如果启用 Proguard)

    -keep public class com.alibaba.android.arouter.routes.**{*;}
    -keep public class com.alibaba.android.arouter.facade.**{*;}
    -keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}
    
    # Injector class names are derived from the target class name at runtime.
    # Current arouter-api artifacts package this rule automatically; keep it for older/custom setups.
    -keep,allowoptimization,allowshrinking class * {
        @com.alibaba.android.arouter.facade.annotation.Autowired ;
    }
    
    # If you use the byType method to obtain Service, add the following rules to protect the interface:
    -keep interface * implements com.alibaba.android.arouter.facade.template.IProvider
    
    # If single-type injection is used, that is, no interface is defined to implement IProvider, the following rules need to be added to protect the implementation
    # -keep class * implements com.alibaba.android.arouter.facade.template.IProvider
  6. 使用自定义Gradle插件自动加载路由表

    apply plugin: 'com.alibaba.arouter'
    
    buildscript {
        repositories {
            mavenCentral()
        }
    
        dependencies {
            // Replace with the latest version
            classpath "com.alibaba:arouter-register:?"
        }
    }

    可选,使用 ARouter 提供的注册插件自动加载路由表(由 AutoRegister 提供支持)。默认情况下,ARouter 会扫描 dex 文件。
    通过 gradle 插件进行自动注册可以缩短初始化时间,需要注意的是,该插件必须与 1.3.0 以上的 API 一起使用!

    在 Android Gradle Plugin 7.4 或更新版本中,注册插件使用公共的 Scoped Artifacts API 并支持 Gradle 配置缓存。较旧的 AGP 版本使用传统的 Transform API,无法提供可靠的配置缓存复用。

  7. 使用 IDE 插件快速导航到目标类(可选)

    在 Android Studio 插件市场中搜索 ARouter Helper,或直接下载文档上方列出的 Latest version 中的 arouter-idea-plugin zip 安装包,安装插件后无需任何设置,你可以在跳转代码的开头找到一个图标。

📷 原文此处有图片,请前往 GitHub 仓库查看完整内容。
点击图标跳转到代码中标识路径的目标类。

当前插件识别 Java 和 Kotlin 中 `ARouter.getInstance().build(...)` 调用,其路径为字符串字面量或编译时常量,并且可以导航到 `@Route` 目的地。

IV. 高级用法

  1. 通过 URL 跳转

    // Create a new Activity for monitoring Scheme events, and then directly pass url to ARouter
    public class SchemeFilterActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            Uri uri = getIntent().getData();
            ARouter.getInstance().build(uri).navigation();
            finish();
        }
    }

    AndroidManifest.xml

    
        </intent-filter>
    
  2. 解析 URL 中的参数

    // Declare a field for each parameter and annotate it with @Autowired
    @Route(path = "/test/activity")
    public class Test1Activity extends Activity {
        @Autowired
        public String name;
        @Autowired
        int age;
        @Autowired(name = "girl") // Map different parameters in the URL by name
        boolean boy;
        @Autowired
        TestObj obj;    // Support for parsing custom objects, using json pass in URL
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ARouter.getInstance().inject(this);
    
            // ARouter will automatically set value of fields
            Log.d("param", name + age + boy);
        }
    }
    
    // If you need to pass a custom object, Create a new class(Not the custom object class),implement the SerializationService, And use the @Route annotation annotation, E.g:
    @Route(path = "/yourservicegroupname/json")
    public class JsonServiceImpl implements SerializationService {
        @Override
        public void init(Context context) {
    
        }
    
        @Override
        public  T json2Object(String text, Class clazz) {
            return JSON.parseObject(text, clazz);
        }
    
        @Override
        public String object2Json(Object instance) {
            return JSON.toJSONString(instance);
        }
    }
  3. 声明拦截器(拦截跳转过程,AOP)

    // A more classic application is to handle login events during a jump so that there is no need to repeat the login check on the target page.
    // Interceptors will be executed between jumps, multiple interceptors will be executed in order of priority
    @Interceptor(priority = 8, name = "test interceptor")
    public class TestInterceptor implements IInterceptor {
        @Override
        public void process(Postcard postcard, InterceptorCallback callback) {
            ...
            // No problem! hand over control to the framework
            callback.onContinue(postcard);  
    
            // Interrupt routing process
            // callback.onInterrupt(new RuntimeException("Something exception"));      
    
            // The above two types need to call at least one of them, otherwise it will not continue routing
        }
    
        @Override
        public void init(Context context) {
            // Interceptor initialization, this method will be called when sdk is initialized, it will only be called once
        }
    }

    拦截器必须确保每个请求只执行一次。当重定向到登录路由时,终止原始请求,并通常绕过重定向的相同拦截器链:

    callback.onInterrupt(new IllegalStateException("Login is required"));
    ARouter.getInstance()
        .build("/account/login")
        .greenChannel()
        .navigation(postcard.getContext());

    省略两个回调方法会使原始导航保持待处理状态,直到其超时。

  4. 处理跳转结果

    // U can get the result of a single jump
    ARouter.getInstance().build("/test/1").navigation(this, new NavigationCallback() {
        @Override
        public void onFound(Postcard postcard) {
        ...
        }
    
        @Override
        public void onLost(Postcard postcard) {
        ...
        }
    });
    
    // Check the current route table without launching the destination.
    // The route group is loaded lazily; invalid or unavailable paths return false.
    boolean available = ARouter.getInstance().hasRoute("/test/1");
  5. 自定义全局降级策略

    // Implement the DegradeService interface
    @Route(path = "/xxx/xxx")
    public class DegradeServiceImpl implements DegradeService {
        @Override
        public void onLost(Context context, Postcard postcard) {
            // do something.
        }
    
        @Override
        public void init(Context context) {
    
        }
    }
  6. 通过依赖注入解耦:服务管理 -- 暴露服务

    // Declaration interface, other components get the service instance through the interface
    public interface HelloService extends IProvider {
        String sayHello(String name);
    }
    
    @Route(path = "/yourservicegroupname/hello", name = "test service")
    public class HelloServiceImpl implements HelloService {
    
        @Override
        public String sayHello(String name) {
            return "hello, " + name;
        }
    
        @Override
        public void init(Context context) {
    
        }
    }
  7. 通过依赖注入解耦:服务管理 -- 发现服务

    public class Test {
        @Autowired
        HelloService helloService;
    
        @Autowired(name = "/yourservicegroupname/hello")
        HelloService helloService2;
    
        HelloService helloService3;
    
        HelloService helloService4;
    
        public Test() {
            ARouter.getInstance().inject(this);
        }
    
        public void testService() {
            // 1. Use Dependency Injection to discover services, annotate fields with annotations
            helloService.sayHello("Vergil");
            helloService2.sayHello("Vergil");
    
            // 2. Discovering services using dependency lookup, the following two methods are byName and byType
            helloService3 = ARouter.getInstance().navigation(HelloService.class);
            helloService4 = (HelloService) ARouter.getInstance().build("/yourservicegroupname/hello").navigation();
            helloService3.sayHello("Vergil");
            helloService4.sayHello("Vergil");
        }
    }
  8. 预处理服务

    @Route(path = "/xxx/xxx")
    public class PretreatmentServiceImpl implements PretreatmentService {
        @Override
        public boolean onPretreatment(Context context, Postcard postcard) {
            // Do something before the navigation, if you need to handle the navigation yourself, the method returns false
        }
    
        @Override
        public void init(Context context) {
    
        }
    }
  9. 动态注册路由元信息
    适用于具有插件架构的应用或某些需要动态注册路由信息的场景,动态注册可以通过 ARouter 提供的接口实现,目标页面和服务无需使用 @Route 注解标记,同一批次只能注册同一组的路由信息

        ARouter.getInstance().addRouteGroup(new IRouteGroup() {
            @Override
            public void loadInto(Map atlas) {
                atlas.put("/dynamic/activity",      // path
                    RouteMeta.build(
                        RouteType.ACTIVITY,         // Route type
                        TestDynamicActivity.class,  // Target class
                        "/dynamic/activity",        // Path
                        "dynamic",                  // Group
                        0,                          // not need
                        0                           // Extra tag, Used to mark page feature
                    )
                );
            }
        });

五、更多功能

  1. 初始化中的其他设置

    ARouter.openLog(); // Open log
    ARouter.openDebug(); // When using InstantRun, you need to open this switch and turn it off after going online. Otherwise, there is a security risk.
    ARouter.printStackTrace(); // Print thread stack when printing logs
  2. API 描述

    // Build a standard route request
    ARouter.getInstance().build("/home/main").navigation();
    
    // Build a standard route request, via URI
    Uri uri;
    ARouter.getInstance().build(uri).navigation();
    
    // Build a standard route request, startActivityForResult
    // The first parameter must be Activity and the second parameter is RequestCode
    ARouter.getInstance().build("/home/main", "ap").navigation(this, 5);
    
    // Activity Result API: register this launcher unconditionally as an Activity/Fragment field.
    private final ActivityResultLauncher resultLauncher =
        registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                // Handle result.getResultCode() and result.getData()
            });
    
    // ARouter completes the Intent and delegates the launch; the caller owns lifecycle and result handling.
    ARouter.getInstance()
        .build("/home/main")
        .navigation(this, new NavigationLauncher() {
            @Override
            public void launch(Intent intent) {
                resultLauncher.launch(intent);
            }
        }, null);
    
    // Pass Bundle directly
    Bundle params = new Bundle();
    ARouter.getInstance()
        .build("/home/main")
        .with(params)
        .navigation();
    
    // Task-stack flags depend on the launch Context. For REORDER_TO_FRONT in the current task,
    // pass the current Activity explicitly. Calling navigation() without a Context uses the
    // application Context, so Android requires ARouter to also add FLAG_ACTIVITY_NEW_TASK.
    ARouter.getInstance()
        .build("/home/main")
        .withFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
        .navigation(this);
    
    // When comparing with a direct startActivity call, use the same Context and final flags.
    
    // For fragment
    Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation();
    
    // transfer the object 
    ARouter.getInstance()
        .withObject("key", new TestObj("Jack", "Rose"))
        .navigation();
    
    // Think the interface is not enough, you can directly set parameter into Bundle
    ARouter.getInstance()
            .build("/home/main")
            .getExtra();
    
    // Transition animation (regular mode)
    ARouter.getInstance()
        .build("/test/activity2")
        .withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)
        .navigation(this);
    
    // Transition animation (API16+)
    ActivityOptionsCompat compat = ActivityOptionsCompat.
        makeScaleUpAnimation(v, v.getWidth() / 2, v.getHeight() / 2, 0, 0);
    
    // ps. makeSceneTransitionAnimation, When using shared elements, you need to pass in the current Activity in the navigation method
    
    ARouter.getInstance()
        .build("/test/activity2")
        .withOptionsCompat(compat)
        .navigation();
    
    // Use green channel (skip all interceptors)
    ARouter.getInstance().build("/home/main").greenChannel().navigation();
    
    // Use your own log tool to print logs
    ARouter.setLogger();
    
    // Use your custom thread pool
    ARouter.setExecutor();
  3. 获取原始 URI

    String uriStr = getIntent().getStringExtra(ARouter.RAW_URI);
  4. 重写网址

    // Implement the PathReplaceService interface
    @Route(path = "/xxx/xxx")
    public class PathReplaceServiceImpl implements PathReplaceService {
        /**
        * For normal path.
        *
        * @param path raw path
        */
        String forString(String path) {
            // Custom logic
            return path;
        }
    
    /**
        * For uri type.
        *
        * @param uri raw uri
        */
        Uri forUri(Uri uri) {
            // Custom logic
            return url;
        }
    }
  5. 生成路由器文档
    使用 annotationProcessor 的 Java 模块:

    // Edit build.gradle, add option 'AROUTER_GENERATE_DOC = enable'
    // Doc file : build/generated/source/apt/(debug or release)/com/alibaba/android/arouter/docs/arouter-map-of-${moduleName}.json
    android {
        defaultConfig {
            ...
            javaCompileOptions {
                annotationProcessorOptions {
                    arguments = [AROUTER_MODULE_NAME: project.getName(), AROUTER_GENERATE_DOC: "enable"]
                }
            }
        }
    }

    Kotlin 模块必须通过 KAPT 传递相同的选项,而不是通过
    javaCompileOptions。生成的文件位于 build/generated/source/kapt/<variant>/ 下。
    处理器会从用于文件名的模块名中移除非字母数字字符(除了 _);例如,module-kotlin 会生成 arouter-map-of-modulekotlin.json。

    apply plugin: 'kotlin-kapt'
    
    kapt {
        arguments {
            arg("AROUTER_MODULE_NAME", project.name)
            arg("AROUTER_GENERATE_DOC", "enable")
        }
    }

    Using build.gradle.kts:

    plugins {
        kotlin("kapt")
    }
    
    dependencies {
        implementation("com.alibaba:arouter-api:x.x.x")
        kapt("com.alibaba:arouter-compiler:x.x.x")
    }
    
    kapt {
        arguments {
            arg("AROUTER_MODULE_NAME", project.name)
            arg("AROUTER_GENERATE_DOC", "enable")
        }
    }

    不要将 kapt 依赖项替换为 annotationProcessor:javac 处理器无法接收在 Kotlin 源代码上声明的注解。

VI. 其他

  1. 旧版本的 Gradle 插件配置

    apply plugin: 'com.neenbedankt.android-apt'
    
    buildscript {
        repositories {
            mavenCentral()
        }
    
        dependencies {
            classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
        }
    }
    
    apt {
        arguments {
            AROUTER_MODULE_NAME project.getName();
        }
    }
    
    dependencies {
        compile 'com.alibaba:arouter-api:x.x.x'
        apt 'com.alibaba:arouter-compiler:x.x.x'
        ...
    }
  2. Kotlin 项目配置

    // You can refer to the wording in the "module-kotlin" module
    apply plugin: 'kotlin-kapt'
    
    kapt {
        arguments {
            arg("AROUTER_MODULE_NAME", project.getName())
            arg("AROUTER_GENERATE_DOC", "enable") // Optional: generate the route document.
        }
    }
    
    dependencies {
        compile 'com.alibaba:arouter-api:x.x.x'
        kapt 'com.alibaba:arouter-compiler:x.x.x'
        ...
    }

    一个单独的 KSP2 开发编译器 支持路由、提供者、Autowired 和拦截器。它尚未发布;请在迁移模块之前检查其
    Kotlin 字段要求并测试工具链。

七、沟通

  1. 沟通

    1. 钉钉群1

📷 原文此处有图片,请前往 GitHub 仓库查看完整内容。

2. QQ群1

📷 原文此处有图片,请前往 GitHub 仓库查看完整内容。

3. QQ群2

📷 原文此处有图片,请前往 GitHub 仓库查看完整内容。

本站来源与版权声明
  • 本文标题:ARouter - 💪 A framework for assistin
  • 本文链接:https://cn121.com/mobile/alibaba-arouter.html
  • 原项目:alibaba/ARouter 版权归原作者 alibaba 及贡献者所有
  • 收录信息:本站于 2026-10-19 收录本项目,本页所列协议与仓库指标均为收录当时的状态;该日期之后原项目的版本更新与协议变更,本页不作同步。
  • 开源协议:收录时本项目采用 Apache-2.0(查看 LICENSE 原文),本站转载其原始文档(未改动文字,仅剔除图片与无关章节);使用、修改、分发请以该仓库 LICENSE 原文为准。本站对原文仅作排版与图片地址适配, 并保留原项目的 NOTICE 与署名要求。
  • 站点出处:本文首发于 OneTwoOne,收录自 GitHub 开源项目 alibaba/ARouter。
  • 内容说明:本页正文为原项目 README 原文(英文),本站后续会翻译为中文(当前尚未译出),仅剔除了图片与赞助等无关章节、并把相对链接改为绝对地址;页首简介为机器翻译自仓库描述。
  • 引用声明:商业转载、第三方聚合或 AI 检索训练引用时,请务必保留以上来源出处、本文永久链接,以及原项目的版权声明与许可信息。
  • 下架通道:若原项目此后变更或收紧了许可协议、或作者/权利人认为本站的收录方式(译文、排版适配、简介翻译等)超出其授权范围,请通过 xyd3302001@163.com 发送下架通知,并附上项目地址与本页链接。本站核实后将第一时间删除本页内容,或改为不复制原文的目录性收录;署名更正等其他要求可一并提出。