ARouter 源码解析(零) 基本使用
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 源码解析(零) 基本使用相关推荐
- ARouter 源码解析(1.5.2 版本)
文章目录 1.简介 2.ARouter 配置与基本用法 2.1 依赖引入与配置 2.2 基本用法 3.ARouter 编译时原理分析 4.ARouter 源码解析 4.1 ARouter 源码主要代码 ...
- Android项目解耦--路由框架ARouter源码解析
前言 上一篇文章Android项目解耦–路由框架ARouter的使用讲述了ARouter在项目中的使用,这边文章主要对ARouter的源码进行学习和分析. ARouter的结构 ARouter主要由三 ...
- Arouter源码解析(二)——ASM和JavaPoet
Arouter 在不使用gradle插件的情况下,是使用Apt+JavaPoet 来处理,其中调用java文件里面的方法则是用了反射的技术.这应该也是初始化时间长的问题:apt的autoService ...
- 路由框架ARouter最全源码解析
ARouter是2017年阿里巴巴开源的一款Android路由框架,官方定义: ARouter是Android平台中对页面,服务提供路由功能的中间件,提倡简单且够用 有下面几个优势: 1.直接解析UR ...
- ARouter init 源码解析(自动注册的实现)
概要 使用ARouter,我们只需要在必要的地方加上注解,然后在application中init Arouter就可以直接通过代码进行路由跳转了. 为什么我们可以不用写任何注册的代码,就直接跳转到相关 ...
- 【源码解析】如何从零实现一个回归模型?
说明:本文源代码来源于MACHINE LEARNING 2022 SPRING课程,我只是针对源代码进行了一些加工处理.感谢互联网,让我们能免费接触到这些优秀的课程. 前置知识 什么是回归模型?简单说 ...
- 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 ...
- ARouter源码探究
ARouter源码探究 1. 疑问 如何做到支持直接解析标准URL进行跳转,并自动注入参数到目标页面中? 如何做到支持Multidex.InstantRun? 如何做到映射关系按组分类.多级管理,按需 ...
- latch.await java有什么作用_java相关:CountDownLatch源码解析之await()
java相关:CountDownLatch源码解析之await() 发布于 2020-6-18| 复制链接 摘记: CountDownLatch 源码解析-- await(),具体内容如下上一篇文章说 ...
最新文章
- 泛型(派生子类,泛型通配符,类型擦除)
- 网站自动登录功能的设计
- Python中的进程间通信
- 小企业如何才能做强做大?
- sqlserver数据库 表中字段值有空格,如何去除空格(例如char (5) 存入数据不足5位时sqlserver会自动补空格)...
- 【ACL2020论文尝鲜】何时采用BERT更加有效?
- 注册AppStore开发者账号以及收款设置的流程详解(2019最新版)
- 电子商务类网站CDN加速方案
- 各种机械键盘轴的区别,到底什么轴好
- 格斗系统 - Universe Fighting Engine
- Python: 第三方模块(modules)的安装位置 (2014-08-24 23:19:18)转载▼ 标签: site-packages dist-packages 默认安装目录	分类: Pyth
- android 清理缓存动画,Android仿微信清理内存图表动画(解决surfaceView屏幕闪烁问题)demo实例详解...
- DB2使用特殊分隔符处理数据
- 填补国内空白 午芯高科国产首款“电容式”高分辨率MEMS气压计芯片率先上市
- 程序员久坐伤身,站起来,走出去,别回来
- 门禁上的push是什么意思_门禁的NC、NO、COM、PUSH等一系列符号的含义是什么?
- 关于容灾备份的一些思考
- 企业如何选择合适的SaaS软件?
- macos安装joy工具
- 【笔记】区块链的系统架构、数据结构及运行机制