Github源码地址:https://github.com/alibaba/ARouter

一、功能介绍

  1. 支持直接解析标准URL进行跳转,并自动解析参数注入
  2. 支持多模块工程使用
  3. 支持添加多个拦截器,自定义拦截顺序
  4. 支持依赖注入,可单独作为依赖注入框架使用
  5. 支持InstantRun
  6. 支持MultiDex(Google方案)
  7. 映射关系按组分类、多级管理,按需初始化
  8. 支持用户指定全局降级与局部降级策略
  9. 页面、拦截器、服务等组件均自动注册到框架

二、典型应用

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

三、基础功能

  1. 添加依赖和配置

    android {
    defaultConfig {
    ...
    javaCompileOptions {
    annotationProcessorOptions {
    arguments = [ moduleName : project.getName() ]
    }
    }
    }
    } dependencies {
    compile 'com.alibaba:arouter-api:x.x.x'
    annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'
    ...
    }
    // 旧版本gradle插件(< 2.2),可以使用apt插件,配置方法见文末'其他#4'
  2. 添加注解

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

    if (isDebug()) {
    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")
    .navigation();
  5. 添加混淆规则(如果使用了Proguard)

    -keep public class com.alibaba.android.arouter.routes.**{*;}
    -keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}

四、进阶用法

  1. 通过URL跳转

    // 新建一个Activity用于监听Schame事件,之后直接把url传递给ARouter即可
    public class SchameFilterActivity 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.SchameFilterActivity">
    <!-- Schame -->
    <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. 解析URL中的参数

    // 为每一个参数声明一个字段,并使用 @Autowired 标注
    @Route(path = "/test/activity")
    public class Test1Activity extends Activity {
    @Autowired
    public String name;
    @Autowired
    private int age;
    @Autowired(name = "girl") // 通过name来映射URL中的不同参数
    private boolean boy; @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ARouter.getInstance().inject(this); // ARouter会自动对字段进行赋值,无需主动获取
    Log.d("param", name + age + boy);
    }
    }
  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 = "/service/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 = "/service/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("/service/hello").navigation();
    helloService3.sayHello("Vergil");
    helloService4.sayHello("Vergil");
    }
    }

五、更多功能

  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(); // 觉得接口不够多,可以直接拿出Bundle赋值
    ARouter.getInstance()
    .build("/home/main")
    .getExtra(); // 使用绿色通道(跳过所有的拦截器)
    ARouter.getInstance().build("/home/main").greenChannal().navigation(); // 使用自己的日志工具打印日志
    ARouter.setLogger();
  3. 获取原始的URI

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

       // 实现PathReplaceService接口,并加上一个Path内容任意的注解即可
    @Route(path = "/xxx/xxx") // 必须标明注解
    public class PathReplaceServiceImpl implements DegradeService {
    /**
    * 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; // 按照一定的规则处理之后返回处理后的结果
    }
    }

六、其他

  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. Jack 编译链的支持

    • 因为不想让用户主动设置一堆乱七八糟的参数,在获取模块名的时候使用javac的api,使用了Jack之后没有了javac,只能让用户稍稍动动手了
    • 现在任何情况下都需要在build.gradle中配置moduleName了。。。。
  4. 旧版本gradle插件的配置方式

    apply plugin: 'com.neenbedankt.android-apt'
    
    buildscript {
    repositories {
    jcenter()
    } dependencies {
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
    }
    } apt {
    arguments {
    moduleName project.getName();
    }
    } dependencies {
    compile 'com.alibaba:arouter-api:x.x.x'
    apt 'com.alibaba:arouter-compiler:x.x.x'
    ...
    }

    注意:应用宝使用乐固加固后,ARouter的启动器会失效,所以启动器需要改成:

 public static void start(Context context, int communityId, String communityName) {
Intent starter = new Intent(context, CommunityApplyListActivity.class);
starter.putExtra("communityId", communityId);
starter.putExtra("communityName", communityName);
if (!(context instanceof Activity)) {
starter.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(starter);
}

【转载】ARouter-万能路由协议的更多相关文章

  1. 【转载】万能adapter

    adapter总是自己写,其实使用现成的框架会节省不少代码 原文地址:https://github.com/hongyangAndroid/baseAdapter base-adapter Andro ...

  2. 草根程序员如何进入BAT

        首页 最新文章 IT 职场 前端 后端 移动端 数据库 运维 其他技术 - 导航条 - 首页 最新文章 IT 职场 前端 - JavaScript - HTML5 - CSS 后端 - Pyt ...

  3. [转载]Ubuntu 安装 万能五笔 输入法

    原文地址:Ubuntu 安装 万能五笔 输入法作者:庖丁解牛 paul@paul-desktop:~/scripts$ cat ins-ibus-wnwb.sh #!/bin/sh set -e cd ...

  4. 【转载】可被路由的协议 & 路由协议 & 不可被路由的协议 的区别

    原文地址:可被路由的协议 & 路由协议 & 不可被路由的协议 的区别 术语routed protocol(可被路由的协议)和routing protocol(路由协议)经常被混淆.可被 ...

  5. 转载:对比Angular/jQueryUI/Extjs:没有一个框架是万能的

    Angular不能做什么?对比Angular/jQueryUI/Extjs 框架就好比兵器,你得明白你手里拿的是屠龙刀还是倚天剑,刀法主要是砍,剑法主要是刺.对于那些职业喷子和脑残粉,小僧送你们两个字 ...

  6. 打造android偷懒神器———RecyclerView的万能适配器

    转载请注明出处谢谢:http://www.cnblogs.com/liushilin/p/5720926.html 很不好意思让大家久等了,本来昨天就应该写这个的,无奈公司昨天任务比较紧,所以没能按时 ...

  7. 转载ali面

    引言 首先声明,不要再问LZ谁是林萧,林萧就是某著名程序员小说的主角名字. 写这篇文章的目的其实很简单,算是对之前LZ一篇文章的补充和完善. 之前LZ写过一篇<回答阿里社招面试如何准备,顺便谈谈 ...

  8. 转载:[转]如何学好3D游戏引擎编程

      [转]如何学好3D游戏引擎编程 Albert 本帖被 gamengines 从 游戏引擎(Game Engine) 此文为转载,但是值得一看. 此篇文章献给那些为了游戏编程不怕困难的热血青年,它的 ...

  9. Huge Page 是否是拯救性能的万能良药?

    本文将分析是否Huge Page在任何条件下(特别是NUMA架构下)都能带来性能提升. 本博客已经迁移至: http://cenalulu.github.io/ 为了更好的体验,请通过此链接阅读: h ...

随机推荐

  1. ubuntu系统安装mysql二进制压缩包(tar.gz)以及navicat远程连接服务器(linux系统)

    一.ubuntu安装mysql5.6二进制压缩包(tar.gz) 准备 0. 获取 mysql-5.5.15-linux2.6-i686.tar.gz 二进制安装文件 mysql 官网下载页面选择 L ...

  2. [DeeplearningAI笔记]序列模型2.7负采样Negative sampling

    5.2自然语言处理 觉得有用的话,欢迎一起讨论相互学习~Follow Me 2.7 负采样 Negative sampling Mikolov T, Sutskever I, Chen K, et a ...

  3. CountUp.js让页面数字跳动起来

    CountUp.js 无依赖的.轻量级的 JavaScript 类,可以用来快速创建以一种更有趣的动画方式显示数值数据.尽管它的名字叫 countUp,但其实可以在两个方向进行变化,这是根据你传递的 ...

  4. 洛谷 P2345 奶牛集会

    https://www.luogu.org/problem/show?pid=2345 题目描述 约翰的N 头奶牛每年都会参加“哞哞大会”.哞哞大会是奶牛界的盛事.集会上的活动很 多,比如堆干草,跨栅 ...

  5. HDU 1695 容斥

    又是求gcd=k的题,稍微有点不同的是,(i,j)有偏序关系,直接分块好像会出现问题,还好数据规模很小,直接暴力求就行了. /** @Date : 2017-09-15 18:21:35 * @Fil ...

  6. HDU 2239 polya计数 欧拉函数

    这题模数是9937还不是素数,求逆元还得手动求. 项链翻转一样的算一种相当于就是一种类型的置换,那么在n长度内,对于每个i其循环节数为(i,n),但是由于n<=2^32,肯定不能直接枚举,所有考 ...

  7. CF767 C.Garland DFS

    LINK 题意:给定一棵树,每个节点拥有权值,问能否找到两个点,断开它们与父节点的边能使树分成权值和相等的三部分.权值可以为负 思路:进行两遍DFS,第一遍找最深的子树和为sum/3的节点,标记掉找到 ...

  8. IO流-LineNumberReader

    LineNumberReader继承自BufferedReader,比其多了两个方法,用于设置和获取当前行号, setLineNumber(); getLineNumber();

  9. macbook 安装任意来源

    sudo spctl --master-disable Comand+r Csrutil disable Reboot

  10. 【LibreOJ】#6299. 「CodePlus 2018 3 月赛」白金元首与克劳德斯

    [题意]给出坐标系中n个矩形,类型1的矩形每单位时间向x轴正方向移动1个单位,类型2的矩形向y轴正方向,初始矩形不重叠,一个点被矩形覆盖当且仅当它在矩形内部(不含边界),求$(-\infty ,+\i ...