ARouter 源码解析(零) 基本使用

零、要解决的问题

在app的开发中,页面之间的相互跳转是最基本常用的功能。在Android中的跳转一般通过显式intent和隐式intent两种方式实现的,而Android的原生跳转方式会存在一些缺点:

  • 显式intent的实现方式,因为会存在直接的类依赖的问题,导致耦合严重;
  • 隐式intent的实现方式,则会出现规则集中式管理,导致协作变得困难;
  • 配置不够灵活,一般而言配置规则都是在Manifest中的;
  • 跳转过程无法控制,一旦使用了StartActivity()就无法插手其中任何环节了,只能交给系统管理;
  • 组件化开发时不容易实现解耦

一、Arouter简介

Arouter是alibaba推出的一个路由框架

github介绍:一个用于帮助 Android App 进行组件化改造的框架 —— 支持模块间的路由、通信、解耦

具有以下优点:

  • 更简便灵活的配置方式
  • 可以拦截跳转过程进行一些处理
  • 可监听/处理跳转结果
  • 容易实现跨模块的解耦
  • 支持从外部解析URL映射跳转到内部页面

二、Arouter的使用

2.1注解的使用

@Route 用来标记一个可以被路由的页面

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Route {//用来唯一标识一个路由节点String path();//用来将路由结点分组String group() default "";//略 名称,用来生成javadocString name() default "";//对这个页面属性的设置int extras() default Integer.MIN_VALUE;//略 优先级int priority() default -1;
}

@Route标记目前可以用于标记Activity , IProvider的实现类(后文会讲)

@Interceptor 用来标记一个拦截器

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Interceptor {//拦截器的优先级int priority();//略 名称,用来生成javadocString name() default "Default";
}
  • 拦截器可以用于对路由进行拦截、加参等
  • 每一个拦截器都是全局的,而拦截器的调用顺序取决于它们的优先级,优先级高的会先被调用
  • 如果一次路由在某个拦截器中被拦截,后面优先级较低的拦截器就不会接收到这次路由

@Autowired 用于标记需要自动填充的变量

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.CLASS)
public @interface Autowired {//标记变量对应的名字String name() default "";//如果为true,则这个变量为null时会抛出异常(不会检查基本类型)boolean required() default false;//略 描述这个属性String desc() default "";
}

Activity 中使用该注解标志的变量,会在页面被路由打开的时候自动赋予传递的参数值。

2.2 简单用法

Activity的简单跳转

根据path进行跳转

ARouter.getInstance().build("/test/activity").navigation();

携带参数跳转

ARouter.getInstance().build("/test/1").withLong("key1", 666L).withString("key3", "888").withObject("key4", new Test("Jack", "Rose")).navigation();

for result

ARouter.getInstance().build("/home/main", "ap").navigation(this, requestCode);

获取Fragment

Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation();

使用URL跳转

// 新建一个Activity用于监听Schame事件,之后直接把url传递给ARouter即可
public class SchameFilterActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Uri uri = getIntent().getData();ARouter.getInstance().build(uri).navigation();finish();}
}
<activity android:name=".activity.SchameFilterActivity"><!-- Schame --><intent-filter><dataandroid: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>

自动填充参数

// 为每一个参数声明一个字段,并使用 @Autowired 标注
// URL中不能传递Parcelable类型数据,通过ARouter api可以传递Parcelable对象
@Route(path = "/test/activity")
public class Test1Activity extends Activity {@Autowiredpublic String name;@Autowiredint age;@Autowired(name = "girl") // 通过name来映射URL中的不同参数boolean boy;@AutowiredTestObj obj;    // 支持解析自定义对象,URL中使用json传递@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ARouter.getInstance().inject(this);}
}

@Autowired只能在Activity或Fragment用来标记public的变量,变量可以为

传递自定义对象

@Route(path = "/service/json")
public class JsonServiceImpl implements SerializationService {@Overridepublic void init(Context context) {}@Overridepublic <T> T json2Object(String text, Class<T> clazz) {return JSON.parseObject(text, clazz);}@Overridepublic String object2Json(Object instance) {return JSON.toJSONString(instance);}
}

拦截器

@Interceptor(priority = 8, name = "测试用拦截器")
public class TestInterceptor implements IInterceptor {@Overridepublic void process(Postcard postcard, InterceptorCallback callback) {...callback.onContinue(postcard);  // 处理完成,交还控制权// callback.onInterrupt(null);      // 觉得有问题,中断路由流程// 以上两种至少需要调用其中一种,否则不会继续路由}@Overridepublic void init(Context context) {// 拦截器的初始化,会在sdk初始化的时候调用该方法,仅会调用一次}
}

处理跳转结果

// 使用两个参数的navigation方法,可以获取单次跳转的结果
ARouter.getInstance().build("/test/1").navigation(this, new NavigationCallback() {@Overridepublic void onFound(Postcard postcard) {...}@Overridepublic void onLost(Postcard postcard) {...}
});

降级策略

单独降级

ARouter.getInstance().build("/xxx/xxx").navigation(this, new NavCallback() {@Overridepublic void onFound(Postcard postcard) {Log.d("ARouter", "找到了");}@Overridepublic void onLost(Postcard postcard) {Log.d("ARouter", "找不到了");}@Overridepublic void onArrival(Postcard postcard) {Log.d("ARouter", "跳转完了");}@Overridepublic void onInterrupt(Postcard postcard) {Log.d("ARouter", "被拦截了");}
});

全局降级

// 实现DegradeService接口,并加上一个Path内容任意的注解即可
@Route(path = "/xxx/xxx")
public class DegradeServiceImpl implements DegradeService {@Overridepublic void onLost(Context context, Postcard postcard) {// do something.}@Overridepublic void init(Context context) {}
}

注:单独降级优先于全局降级,使用单独降级后不会再调用全局降级

为页面声明更多信息

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

服务

暴露服务

// 声明接口,其他组件通过接口来调用服务
public interface HelloService extends IProvider {String sayHello(String name);
}// 实现接口
@Route(path = "/service/hello", name = "测试服务")
public class HelloServiceImpl implements HelloService {@Overridepublic String sayHello(String name) {return "hello, " + name;}@Overridepublic void init(Context context) {}
}

发现服务

public class Test {@AutowiredHelloService 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和byTypehelloService3 = ARouter.getInstance().navigation(HelloService.class);helloService4 = (HelloService) ARouter.getInstance().build("/service/hello").navigation();helloService3.sayHello("Vergil");helloService4.sayHello("Vergil");}
}

ARouter的分组概念

Root -> Group -> Activity

  • SDK中针对所有的路径(/test/1 /test/2)进行分组,
  • 可以通过 @Route 注解主动指定分组,否则使用路径中第一段字符串(/*/)作为分组
  • ARouter 初始化时只会初始化Root节点

ARouter 源码解析(零) 基本使用相关推荐

  1. ARouter 源码解析(1.5.2 版本)

    文章目录 1.简介 2.ARouter 配置与基本用法 2.1 依赖引入与配置 2.2 基本用法 3.ARouter 编译时原理分析 4.ARouter 源码解析 4.1 ARouter 源码主要代码 ...

  2. Android项目解耦--路由框架ARouter源码解析

    前言 上一篇文章Android项目解耦–路由框架ARouter的使用讲述了ARouter在项目中的使用,这边文章主要对ARouter的源码进行学习和分析. ARouter的结构 ARouter主要由三 ...

  3. Arouter源码解析(二)——ASM和JavaPoet

    Arouter 在不使用gradle插件的情况下,是使用Apt+JavaPoet 来处理,其中调用java文件里面的方法则是用了反射的技术.这应该也是初始化时间长的问题:apt的autoService ...

  4. 路由框架ARouter最全源码解析

    ARouter是2017年阿里巴巴开源的一款Android路由框架,官方定义: ARouter是Android平台中对页面,服务提供路由功能的中间件,提倡简单且够用 有下面几个优势: 1.直接解析UR ...

  5. ARouter init 源码解析(自动注册的实现)

    概要 使用ARouter,我们只需要在必要的地方加上注解,然后在application中init Arouter就可以直接通过代码进行路由跳转了. 为什么我们可以不用写任何注册的代码,就直接跳转到相关 ...

  6. 【源码解析】如何从零实现一个回归模型?

    说明:本文源代码来源于MACHINE LEARNING 2022 SPRING课程,我只是针对源代码进行了一些加工处理.感谢互联网,让我们能免费接触到这些优秀的课程. 前置知识 什么是回归模型?简单说 ...

  7. The Wide and Deep Learning Model(译文+Tensorlfow源码解析) 原创 2017年11月03日 22:14:47 标签: 深度学习 / 谷歌 / tensorf

    The Wide and Deep Learning Model(译文+Tensorlfow源码解析) 原创 2017年11月03日 22:14:47 标签: 深度学习 / 谷歌 / tensorfl ...

  8. ARouter源码探究

    ARouter源码探究 1. 疑问 如何做到支持直接解析标准URL进行跳转,并自动注入参数到目标页面中? 如何做到支持Multidex.InstantRun? 如何做到映射关系按组分类.多级管理,按需 ...

  9. latch.await java有什么作用_java相关:CountDownLatch源码解析之await()

    java相关:CountDownLatch源码解析之await() 发布于 2020-6-18| 复制链接 摘记: CountDownLatch 源码解析-- await(),具体内容如下上一篇文章说 ...

最新文章

  1. 泛型(派生子类,泛型通配符,类型擦除)
  2. 网站自动登录功能的设计
  3. Python中的进程间通信
  4. 小企业如何才能做强做大?
  5. sqlserver数据库 表中字段值有空格,如何去除空格(例如char (5) 存入数据不足5位时sqlserver会自动补空格)...
  6. 【ACL2020论文尝鲜】何时采用BERT更加有效?
  7. 注册AppStore开发者账号以及收款设置的流程详解(2019最新版)
  8. 电子商务类网站CDN加速方案
  9. 各种机械键盘轴的区别,到底什么轴好
  10. 格斗系统 - Universe Fighting Engine
  11. Python: 第三方模块(modules)的安装位置 (2014-08-24 23:19:18)转载▼ 标签: site-packages dist-packages 默认安装目录 分类: Pyth
  12. android 清理缓存动画,Android仿微信清理内存图表动画(解决surfaceView屏幕闪烁问题)demo实例详解...
  13. DB2使用特殊分隔符处理数据
  14. 填补国内空白 午芯高科国产首款“电容式”高分辨率MEMS气压计芯片率先上市
  15. 程序员久坐伤身,站起来,走出去,别回来
  16. 门禁上的push是什么意思_门禁的NC、NO、COM、PUSH等一系列符号的含义是什么?
  17. 关于容灾备份的一些思考
  18. 企业如何选择合适的SaaS软件?
  19. macos安装joy工具
  20. 【笔记】区块链的系统架构、数据结构及运行机制

热门文章

  1. Python输入账号密码判断是否正确并输出,典型案例-百钱买百鸡的两个程序代码
  2. dw中css目标规则命名,css 常用样式命名规则
  3. 最全的mysql常用语句大全
  4. 短视频平台达人为什么那么赚钱?
  5. 移动商务,还是短信商务?
  6. 英语词汇 talk down to 的中英翻译解释和例子
  7. domino 调用java_java调用domino
  8. 逗号运算符java_简单的java计算器 实现了重复标点及运算符连点限制
  9. 算法随笔 — 树结构基础 — 并查集
  10. Database connections will be migrated