4 Star 47 Fork 13

Gitee 极速下载 / ARouter

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
此仓库是为了提升国内下载速度的镜像仓库,每日同步一次。 原始仓库: https://github.com/alibaba/ARouter
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0
    一个用于帮助 Android App 进行组件化改造的框架 —— 支持模块间的路由、通信、解耦

English

Join the chat at https://gitter.im/alibaba/ARouter Hex.pm

最新版本

模块 arouter-api arouter-compiler arouter-register arouter-idea-plugin
最新版本 Download Download Download as plugin

Demo展示

Demo apk下载Demo Gif

一、功能介绍

  1. 支持直接解析标准URL进行跳转,并自动注入参数到目标页面中
  2. 支持多模块工程使用
  3. 支持添加多个拦截器,自定义拦截顺序
  4. 支持依赖注入,可单独作为依赖注入框架使用
  5. 支持InstantRun
  6. 支持MultiDex(Google方案)
  7. 映射关系按组分类、多级管理,按需初始化
  8. 支持用户指定全局降级与局部降级策略
  9. 页面、拦截器、服务等组件均自动注册到框架
  10. 支持多种方式配置转场动画
  11. 支持获取Fragment
  12. 完全支持Kotlin以及混编(配置见文末 其他#5)
  13. 支持第三方 App 加固(使用 arouter-register 实现自动注册)
  14. 支持生成路由文档
  15. 提供 IDE 插件便捷的关联路径和目标类
  16. 支持增量编译(开启文档生成后无法增量编译)
  17. 支持动态注册路由信息

二、典型应用

  1. 从外部URL映射到内部页面,以及参数传递与解析
  2. 跨模块页面跳转,模块间解耦
  3. 拦截跳转过程,处理登陆、埋点等逻辑
  4. 跨模块API调用,通过控制反转来做组件解耦

三、基础功能

  1. 添加依赖和配置

    android {
        defaultConfig {
            ...
            javaCompileOptions {
                annotationProcessorOptions {
                    arguments = [AROUTER_MODULE_NAME: project.getName()]
                }
            }
        }
    }
    
    dependencies {
        // 替换成最新版本, 需要注意的是api
        // 要与compiler匹配使用,均使用最新版可以保证兼容
        compile 'com.alibaba:arouter-api:x.x.x'
        annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'
        ...
    }
    // 旧版本gradle插件(< 2.2),可以使用apt插件,配置方法见文末'其他#4'
    // Kotlin配置参考文末'其他#5'
  2. 添加注解

    // 在支持路由的页面上添加注解(必选)
    // 这里的路径需要注意的是至少需要有两级,/xx/xx
    @Route(path = "/test/activity")
    public class YourActivity extend Activity {
        ...
    }
  3. 初始化SDK

    if (isDebug()) {           // 这两行必须写在init之前,否则这些配置在init过程中将无效
        ARouter.openLog();     // 打印日志
        ARouter.openDebug();   // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
    }
    ARouter.init(mApplication); // 尽可能早,推荐在Application中初始化
  4. 发起路由操作

    // 1. 应用内简单的跳转(通过URL跳转在'进阶用法'中)
    ARouter.getInstance().build("/test/activity").navigation();
    
    // 2. 跳转并携带参数
    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{*;}
    
    # 如果使用了 byType 的方式获取 Service,需添加下面规则,保护接口
    -keep interface * implements com.alibaba.android.arouter.facade.template.IProvider
    
    # 如果使用了 单类注入,即不定义接口实现 IProvider,需添加下面规则,保护实现
    # -keep class * implements com.alibaba.android.arouter.facade.template.IProvider
  6. 使用 Gradle 插件实现路由表的自动加载 (可选)

    apply plugin: 'com.alibaba.arouter'
    
    buildscript {
        repositories {
            mavenCentral()
        }
    
        dependencies {
            classpath "com.alibaba:arouter-register:?"
        }
    }

    可选使用,通过 ARouter 提供的注册插件进行路由表的自动加载(power by AutoRegister), 默认通过扫描 dex 的方式 进行加载通过 gradle 插件进行自动注册可以缩短初始化时间解决应用加固导致无法直接访问 dex 文件,初始化失败的问题,需要注意的是,该插件必须搭配 api 1.3.0 以上版本使用!

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

    在 Android Studio 插件市场中搜索 ARouter Helper, 或者直接下载文档上方 最新版本 中列出的 arouter-idea-plugin zip 安装包手动安装,安装后 插件无任何设置,可以在跳转代码的行首找到一个图标 (navigation) 点击该图标,即可跳转到标识了代码中路径的目标类

四、进阶用法

  1. 通过URL跳转

    // 新建一个Activity用于监听Scheme事件,之后直接把url传递给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

    <activity android:name=".activity.SchemeFilterActivity">
        <!-- Scheme -->
        <intent-filter>
            <data
            android:host="m.aliyun.com"
            android:scheme="arouter"/>
    
            <action android:name="android.intent.action.VIEW"/>
    
            <category android:name="android.intent.category.DEFAULT"/>
            <category android:name="android.intent.category.BROWSABLE"/>
        </intent-filter>
    </activity>
  2. 解析参数

    // 为每一个参数声明一个字段,并使用 @Autowired 标注
    // URL中不能传递Parcelable类型数据,通过ARouter api可以传递Parcelable对象
    @Route(path = "/test/activity")
    public class Test1Activity extends Activity {
        @Autowired
        public String name;
        @Autowired
        int age;
        
        // 通过name来映射URL中的不同参数
        @Autowired(name = "girl") 
        boolean boy;
        
        // 支持解析自定义对象,URL中使用json传递
        @Autowired
        TestObj obj;      
        
        // 使用 withObject 传递 List 和 Map 的实现了
        // Serializable 接口的实现类(ArrayList/HashMap)
        // 的时候,接收该对象的地方不能标注具体的实现类类型
        // 应仅标注为 List 或 Map,否则会影响序列化中类型
        // 的判断, 其他类似情况需要同样处理        
        @Autowired
        List<TestObj> list;
        @Autowired
        Map<String, List<TestObj>> map;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ARouter.getInstance().inject(this);
    
        // ARouter会自动对字段进行赋值,无需主动获取
        Log.d("param", name + age + boy);
        }
    }
    
    
    // 如果需要传递自定义对象,新建一个类(并非自定义对象类),然后实现 SerializationService,并使用@Route注解标注(方便用户自行选择序列化方式),例如:
    @Route(path = "/yourservicegroupname/json")
    public class JsonServiceImpl implements SerializationService {
        @Override
        public void init(Context context) {
    
        }
    
        @Override
        public <T> T json2Object(String text, Class<T> clazz) {
            return JSON.parseObject(text, clazz);
        }
    
        @Override
        public String object2Json(Object instance) {
            return JSON.toJSONString(instance);
        }
    }
  3. 声明拦截器(拦截跳转过程,面向切面编程)

    // 比较经典的应用就是在跳转过程中处理登陆事件,这样就不需要在目标页重复做登陆检查
    // 拦截器会在跳转之间执行,多个拦截器会按优先级顺序依次执行
    @Interceptor(priority = 8, name = "测试用拦截器")
    public class TestInterceptor implements IInterceptor {
        @Override
        public void process(Postcard postcard, InterceptorCallback callback) {
        ...
        callback.onContinue(postcard);  // 处理完成,交还控制权
        // callback.onInterrupt(new RuntimeException("我觉得有点异常"));      // 觉得有问题,中断路由流程
    
        // 以上两种至少需要调用其中一种,否则不会继续路由
        }
    
        @Override
        public void init(Context context) {
        // 拦截器的初始化,会在sdk初始化的时候调用该方法,仅会调用一次
        }
    }
  4. 处理跳转结果

    // 使用两个参数的navigation方法,可以获取单次跳转的结果
    ARouter.getInstance().build("/test/1").navigation(this, new NavigationCallback() {
        @Override
        public void onFound(Postcard postcard) {
        ...
        }
    
        @Override
        public void onLost(Postcard postcard) {
        ...
        }
    });
  5. 自定义全局降级策略

    // 实现DegradeService接口,并加上一个Path内容任意的注解即可
    @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. 为目标页面声明更多信息

    // 我们经常需要在目标页面中配置一些属性,比方说"是否需要登陆"之类的
    // 可以通过 Route 注解中的 extras 属性进行扩展,这个属性是一个 int值,换句话说,单个int有4字节,也就是32位,可以配置32个开关
    // 剩下的可以自行发挥,通过字节操作可以标识32个开关,通过开关标记目标页面的一些属性,在拦截器中可以拿到这个标记进行业务逻辑判断
    @Route(path = "/test/activity", extras = Consts.XXXX)
  7. 通过依赖注入解耦:服务管理(一) 暴露服务

    // 声明接口,其他组件通过接口来调用服务
    public interface HelloService extends IProvider {
        String sayHello(String name);
    }
    
    // 实现接口
    @Route(path = "/yourservicegroupname/hello", name = "测试服务")
    public class HelloServiceImpl implements HelloService {
    
        @Override
        public String sayHello(String name) {
        return "hello, " + name;
        }
    
        @Override
        public void init(Context context) {
    
        }
    }
  8. 通过依赖注入解耦:服务管理(二) 发现服务

    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. (推荐)使用依赖注入的方式发现服务,通过注解标注字段,即可使用,无需主动获取
        // Autowired注解中标注name之后,将会使用byName的方式注入对应的字段,不设置name属性,会默认使用byType的方式发现服务(当同一接口有多个实现的时候,必须使用byName的方式发现服务)
        helloService.sayHello("Vergil");
        helloService2.sayHello("Vergil");
    
        // 2. 使用依赖查找的方式发现服务,主动去发现服务并使用,下面两种方式分别是byName和byType
        helloService3 = ARouter.getInstance().navigation(HelloService.class);
        helloService4 = (HelloService) ARouter.getInstance().build("/yourservicegroupname/hello").navigation();
        helloService3.sayHello("Vergil");
        helloService4.sayHello("Vergil");
        }
    }
  9. 预处理服务

    // 实现 PretreatmentService 接口,并加上一个Path内容任意的注解即可
    @Route(path = "/xxx/xxx")
    public class PretreatmentServiceImpl implements PretreatmentService {
        @Override
        public boolean onPretreatment(Context context, Postcard postcard) {
            // 跳转前预处理,如果需要自行处理跳转,该方法返回 false 即可
        }
    
        @Override
        public void init(Context context) {
    
        }
    }
  10. 动态注册路由信息 适用于部分插件化架构的App以及需要动态注册路由信息的场景,可以通过 ARouter 提供的接口实现动态注册 路由信息,目标页面和服务可以不标注 @Route 注解,注意:同一批次仅允许相同 group 的路由信息注册

        ARouter.getInstance().addRouteGroup(new IRouteGroup() {
            @Override
            public void loadInto(Map<String, RouteMeta> atlas) {
                atlas.put("/dynamic/activity",      // path
                    RouteMeta.build(
                        RouteType.ACTIVITY,         // 路由信息
                        TestDynamicActivity.class,  // 目标的 Class
                        "/dynamic/activity",        // Path
                        "dynamic",                  // Group, 尽量保持和 path 的第一段相同
                        0,                          // 优先级,暂未使用
                        0                           // Extra,用于给页面打标
                    )
                );
            }
        });

五、更多功能

  1. 初始化中的其他设置

    ARouter.openLog(); // 开启日志
    ARouter.openDebug(); // 使用InstantRun的时候,需要打开该开关,上线之后关闭,否则有安全风险
    ARouter.printStackTrace(); // 打印日志的时候打印线程堆栈
  2. 详细的API说明

    // 构建标准的路由请求
    ARouter.getInstance().build("/home/main").navigation();
    
    // 构建标准的路由请求,并指定分组
    ARouter.getInstance().build("/home/main", "ap").navigation();
    
    // 构建标准的路由请求,通过Uri直接解析
    Uri uri;
    ARouter.getInstance().build(uri).navigation();
    
    // 构建标准的路由请求,startActivityForResult
    // navigation的第一个参数必须是Activity,第二个参数则是RequestCode
    ARouter.getInstance().build("/home/main", "ap").navigation(this, 5);
    
    // 直接传递Bundle
    Bundle params = new Bundle();
    ARouter.getInstance()
        .build("/home/main")
        .with(params)
        .navigation();
    
    // 指定Flag
    ARouter.getInstance()
        .build("/home/main")
        .withFlags();
        .navigation();
    
    // 获取Fragment
    Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation();
                        
    // 对象传递
    ARouter.getInstance()
        .withObject("key", new TestObj("Jack", "Rose"))
        .navigation();
    
    // 觉得接口不够多,可以直接拿出Bundle赋值
    ARouter.getInstance()
            .build("/home/main")
            .getExtra();
    
    // 转场动画(常规方式)
    ARouter.getInstance()
        .build("/test/activity2")
        .withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)
        .navigation(this);
    
    // 转场动画(API16+)
    ActivityOptionsCompat compat = ActivityOptionsCompat.
        makeScaleUpAnimation(v, v.getWidth() / 2, v.getHeight() / 2, 0, 0);
    
    // ps. makeSceneTransitionAnimation 使用共享元素的时候,需要在navigation方法中传入当前Activity
    
    ARouter.getInstance()
        .build("/test/activity2")
        .withOptionsCompat(compat)
        .navigation();
            
    // 使用绿色通道(跳过所有的拦截器)
    ARouter.getInstance().build("/home/main").greenChannel().navigation();
    
    // 使用自己的日志工具打印日志
    ARouter.setLogger();
    
    // 使用自己提供的线程池
    ARouter.setExecutor();
  3. 获取原始的URI

    String uriStr = getIntent().getStringExtra(ARouter.RAW_URI);
  4. 重写跳转URL

    // 实现PathReplaceService接口,并加上一个Path内容任意的注解即可
    @Route(path = "/xxx/xxx") // 必须标明注解
    public class PathReplaceServiceImpl implements PathReplaceService {
        /**
        * For normal path.
        *
        * @param path raw path
        */
        String forString(String path) {
        return path;    // 按照一定的规则处理之后返回处理后的结果
        }
    
    /**
        * For uri type.
        *
        * @param uri raw uri
        */
    Uri forUri(Uri uri) {
        return url;    // 按照一定的规则处理之后返回处理后的结果
    }
    }
  5. 生成路由文档

    // 更新 build.gradle, 添加参数 AROUTER_GENERATE_DOC = enable
    // 生成的文档路径 : 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"]
                }
            }
        }
    }

六、其他

  1. 路由中的分组概念

    • SDK中针对所有的路径(/test/1 /test/2)进行分组,分组只有在分组中的某一个路径第一次被访问的时候,该分组才会被初始化
    • 可以通过 @Route 注解主动指定分组,否则使用路径中第一段字符串(/*/)作为分组
    • 注意:一旦主动指定分组之后,应用内路由需要使用 ARouter.getInstance().build(path, group) 进行跳转,手动指定分组,否则无法找到
    @Route(path = "/test/1", group = "app")
  2. 拦截器和服务的异同

    • 拦截器和服务所需要实现的接口不同,但是结构类似,都存在 init(Context context) 方法,但是两者的调用时机不同
    • 拦截器因为其特殊性,会被任何一次路由所触发,拦截器会在ARouter初始化的时候异步初始化,如果第一次路由的时候拦截器还没有初始化结束,路由会等待,直到初始化完成。
    • 服务没有该限制,某一服务可能在App整个生命周期中都不会用到,所以服务只有被调用的时候才会触发初始化操作
  3. 旧版本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'
        ...
    }
  4. Kotlin项目中的配置方式

    // 可以参考 module-kotlin 模块中的写法
    apply plugin: 'kotlin-kapt'
    
    kapt {
        arguments {
            arg("AROUTER_MODULE_NAME", project.getName())
        }
    }
    
    dependencies {
        compile 'com.alibaba:arouter-api:x.x.x'
        kapt 'com.alibaba:arouter-compiler:x.x.x'
        ...
    }

七、Q&A

  1. "W/ARouter::: ARouter::No postcard![ ]"

    这个Log正常的情况下也会打印出来,如果您的代码中没有实现DegradeService和PathReplaceService的话,因为ARouter本身的一些功能也依赖 自己提供的Service管理功能,ARouter在跳转的时候会尝试寻找用户实现的PathReplaceService,用于对路径进行重写(可选功能),所以如果您没有 实现这个服务的话,也会抛出这个日志

    推荐在app中实现DegradeService、PathReplaceService

  2. "W/ARouter::: ARouter::There is no route match the path [/xxx/xxx], in group [xxx][ ]"

    • 通常来说这种情况是没有找到目标页面,目标不存在
    • 如果这个页面是存在的,那么您可以按照下面的步骤进行排查
      1. 检查目标页面的注解是否配置正确,正确的注解形式应该是 (@Route(path="/test/test"), 如没有特殊需求,请勿指定group字段,废弃功能)
      2. 检查目标页面所在的模块的gradle脚本中是否依赖了 arouter-compiler sdk (需要注意的是,要使用apt依赖,而不是compile关键字依赖)
      3. 检查编译打包日志,是否出现了形如 ARouter::Compiler >>> xxxxx 的日志,日志中会打印出发现的路由目标
      4. 启动App的时候,开启debug、log(openDebug/openLog), 查看映射表是否已经被扫描出来,形如 D/ARouter::: LogisticsCenter has already been loaded, GroupIndex[4],GroupIndex > 0
  3. 开启InstantRun之后无法跳转(高版本Gradle插件下无法跳转)?

    因为开启InstantRun之后,很多类文件不会放在原本的dex中,需要单独去加载,ARouter默认不会去加载这些文件,因为安全原因,只有在开启了openDebug之后 ARouter才回去加载InstantRun产生的文件,所以在以上的情况下,需要在init之前调用openDebug

  4. TransformException:java.util.zip.ZipException: duplicate entry ....

    ARouter有按组加载的机制,关于分组可以参考 6-1 部分,ARouter允许一个module中存在多个分组,但是不允许多个module中存在相同的分组,会导致映射文件冲突

  5. Kotlin类中的字段无法注入如何解决?

    首先,Kotlin中的字段是可以自动注入的,但是注入代码为了减少反射,使用的字段赋值的方式来注入的,Kotlin默认会生成set/get方法,并把属性设置为private 所以只要保证Kotlin中字段可见性不是private即可,简单解决可以在字段上添加 @JvmField

  6. 通过URL跳转之后,在intent中拿不到参数如何解决?

    需要注意的是,如果不使用自动注入,那么可以不写 ARouter.getInstance().inject(this),但是需要取值的字段仍然需要标上 @Autowired 注解,因为 只有标上注解之后,ARouter才能知道以哪一种数据类型提取URL中的参数并放入Intent中,这样您才能在intent中获取到对应的参数

  7. 新增页面之后,无法跳转?

    ARouter加载Dex中的映射文件会有一定耗时,所以ARouter会缓存映射文件,直到新版本升级(版本号或者versionCode变化),而如果是开发版本(ARouter.openDebug()), ARouter 每次启动都会重新加载映射文件,开发阶段一定要打开 Debug 功能

八、其他

  1. 沟通和交流

    1. 钉钉交流群1

      qq

    2. QQ 交流群1

      qq

    3. QQ 交流群2

      qq

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

简介

ARouter 是阿里开源的一个 Android 路由中间件,用于对页面、服务提供路由功能 展开 收起
Java 等 4 种语言
Apache-2.0
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Java
1
https://gitee.com/mirrors/ARouter.git
git@gitee.com:mirrors/ARouter.git
mirrors
ARouter
ARouter
develop

搜索帮助