一、简介

Android平台中对页面、服务提供路由功能(跳转)的一个库

1.1 最新版本

模块 arouter-api arouter-compiler arouter-annotation
最新版本

1.2 实例图片

1.3 功能介绍

  1. 支持直接解析标准URL进行跳转,并自动注入参数到目标页面中
  2. 支持多模块工程使用
  3. 支持添加多个拦截器,自定义拦截顺序
  4. 支持依赖注入,可单独作为依赖注入框架使用
  5. 支持InstantRun
  6. 支持MultiDex(Google方案)
  7. 映射关系按组分类、多级管理,按需初始化
  8. 支持用户指定全局降级与局部降级策略
  9. 页面、拦截器、服务等组件均自动注册到框架
  10. 支持多种方式配置转场动画
  11. 支持获取Fragment
  12. 完全支持Kotlin以及混编(配置见文末 其他#5)

1.4 应用场景

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

二、使用方法

1.1 导包

导包现在分java和kotlin, java的导包方法如下,在根moduel的build.gradle添加如下内容:

android {defaultConfig {...javaCompileOptions {annotationProcessorOptions {arguments = [ moduleName : project.getName() ]}}}
}dependencies {// 替换成最新版本, 需要注意的是api,最新版本看文章开头// 要与compiler匹配使用,均使用最新版可以保证兼容compile 'com.alibaba:arouter-api:x.x.x'annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'...
}

如果java使用的是apt,导入方法则是如下:

apply plugin: 'com.neenbedankt.android-apt'buildscript {repositories {jcenter()}dependencies {classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'}
}apt {arguments {moduleName project.getName();}
}dependencies {//这里填写最新的版本看文章开始compile 'com.alibaba:arouter-api:x.x.x'apt 'com.alibaba:arouter-compiler:x.x.x'...
}

kotlin的导包方法如下,在根moduel的build.gradle添加如下内容:

apply plugin: 'kotlin-kapt'kapt {arguments {arg("moduleName", project.getName())}
}dependencies {//这里填写最新的版本,看文章开始compile 'com.alibaba:arouter-api:x.x.x'kapt 'com.alibaba:arouter-compiler:x.x.x'...
}

1.2 初始化

解析在代码中

class BaseApplication :Application(){override fun onCreate() {super.onCreate()if(BuildConfig.DEBUG){ //如果在debug模式下// 打印日志,默认关闭ARouter.openLog()// 开启调试模式,默认关闭(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)ARouter.openDebug()// 打印日志的时候打印线程堆栈ARouter.printStackTrace()} // 尽可能早,推荐在Application中初始化ARouter.init(this) }
}

1.3 普通的Activity跳转

方法又有Uri和path两种

利用ARouter的path方法:

例如我要在 AActivity跳转到BActivity,这时候AActivity的代码是这样子的(记得编写manifest):

    override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)textView = findViewById(R.id.textView) as TextViewtextView!!.setOnClickListener {ARouter.getInstance().build("/path/bactivity").navigation()}}

然后BActivity的代码是这样子的(记得编写manifest):

@Route(path = "/path/bactivity")
class BActivity :AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)}}

可以看到,跳转是利用build方法里面的一个字符串进行标识,然后调用navigation进行跳转到 注解@Route标记的字符串路径。

利用Uri方法:

例如上面的AActivity里面的跳转方法改为:

    override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)textView = findViewById(R.id.textView) as TextViewtextView!!.setOnClickListener {val uri = Uri.parse("/path/bactivity")ARouter.getInstance().build(uri).navigation()}}

然后BActivity保持不变,效果是一样的。

PS: Uri.parse的时候,改为完整路径也是支持的,例如改为val uri = Uri.parse(“tpnet://m.aliyun.com/path/bactivity”),也可以成功跳转到BActivity

1.4 普通的Activity跳转参数

调用with对应的类型即可,

ARouter.getInstance().build(RouterPath.PAGE_TEST1)//第一个参数为key,第二个参数为值.withLong("longKey", 0x555555L).withString("stringKey", "66666").navigation()

在接收的activity解析的时候,获取到extras,get对应的类型即可:

    val extrsa = intent.extrasprintln(extrsa.getLong("longKey"))println(extrsa.getString("stringKey"))

1.5普通的Activity跳转动画

添加跳转动画有两种方法,一个是兼容,一个是只能大于等于sdk16才能用。

兼容方法:

使用withTransition方法,添加 进入动画,退出动画即可

ARouter.getInstance().build("/path/bactivity")//参数1为打开的Activity的进入动画,参数2为当前的Activity的退出动画.withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom).navigation(this);

sdk大于等于16的动画方法:

利用withOptionsCompat添加ActivityOptionsCompat对象,

if (Build.VERSION.SDK_INT >= 16) {ActivityOptionsCompat compat = ActivityOptionsCompat.makeScaleUpAnimation(v, v.getWidth() / 2, v.getHeight() / 2, 0, 0);ARouter.getInstance().build("/path/bactivity").withOptionsCompat(compat).navigation();
} else {Toast.makeText(this, "API < 16,不支持新版本动画", Toast.LENGTH_SHORT).show();
}

PS: akeSceneTransitionAnimation 使用共享元素的时候,需要在navigation方法中传入当前Activity

三、 Url跳转

Url跳转就是可以根据url来跳转,可以从网页跳到Activity

3.1 网页url正常跳转Activity

首先定义一个Activity作为中转,网页的链接都跳到这个Activity,然后再从这个Activity打开网页需要打开的Activity

class SchemeFilterActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)ARouter.getInstance().build(intent.data).navigation(this,object: NavCallback() {override fun onArrival(postcard: Postcard?) {finish()}})}
}

该Activity的manifest为:

<activity android:name=".Url.SchemeFilterActivity"><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>

然后定义你要跳转到的Activity,这里定义一个UrlTargetActivity (记得在Manifest说明):

@Route(path = "/test/activity1")
class UrlTargetActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_url_target)val tvContent = findViewById(R.id.content) as TextViewtvContent.text = "当前页面是:" + this@UrlTargetActivity::class.java.name}
}

然后在手机打开一个网页,网页内容为:

<a href="arouter://m.aliyun.com/test/activity1">arouter://m.aliyun.com/test/activity1</a></p>

点击了这个网页链接之后,就到根据"arouter://m.aliyun.com(scheme://host)跳转到SchemeFilterActivity这个Activity,然后在这个Activity利用ARouter 根据path = test/activity1跳转到UrlTargetActivity

3.2 Url跳转带常用类型参数

上面的网页链接添加name、age、sex三个参数,例如:

<p><a href="arouter://m.aliyun.com/test/activity1?name=tpnet&age=21&sex=true">arouter://m.aliyun.com/test/activity1</a></p>

然后,在目标Activity: UrlTargetActivity修改为:

@Route(path = "/test/activity1")
class UrlTargetActivity : AppCompatActivity() {@JvmField@Autowiredvar name: String = ""@JvmField@Autowiredvar age: Int = 0@JvmField@Autowired(name = "sex")var gender: Boolean = falseoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_url_target)val tvContent = findViewById(R.id.content) as TextViewtvContent.text = "当前页面是:" + this@UrlTargetActivity::class.java.nameARouter.getInstance().inject(this)tvContent.text = tvContent.text as String + "\n$name - $age - $gender"}
}

可以看到,使用@Autowired 这个注解变量,然后在onCreate中使用ARouter.getInstance().inject(this) 进行注入,即可得到参数。

那参数怎么样对应变量呢?

  • 1是根据变量名
  • 2是Autowired注解里面有个属性name,这个属性指定参数名称

    PS: @JvmField这个注解,是因为我用的是Kotlin,ARouter使用的是java,所以为了兼容,需要加这个注解

3.3 Url跳转带自定义类型参数

网页通过传递json参数,然后ARouter帮你自动转换为你的自定义对象。

例如,网页链接为:

<p><a href="arouter://m.aliyun.com/test/activity1?name=tpnet&age=21&sex=true&obj=%7B%22name%22:%22jack%22,%22id%22:666%7D">带json自定义对象</a></p>

然后写一个类,实现SerializationService接口,用来实现json的序列化和反序列化。注意这个类也需要添加path,内容不规定

//这里需要添加path,内容随便
@Route(path = "/service/json")
class JsonObjectImpl : SerializationService {override fun init(context: Context?) {}//json字符串转换为对象override fun <T : Any?> json2Object(json: String?, clazz: Class<T>?): T {Log.e("@@","json:"+json)return JSON.parseObject(json, clazz)}//自定义对象转换为json字符串override fun object2Json(instance: Any?): String = JSON.toJSONString(instance)
}

然后就是自定义的对象:

class TestObj() {var name: String = ""     //这里变量名称对应Url的json的keyvar id: Int = 0override fun toString(): String = "TestObj(name='$name', id=$id)"}

然后要打开的目标Activtiy接收自定义对象,如常一样,加一个变量即可,记得变量名字要和url的key一致,或者在Autowired注解添加name属性

    @JvmField@Autowiredvar obj: TestObj? = null

PS: 也支持Parcelable

四、 跳转拦截器

拦截器的意思是,例如你想在 AActivity跳到BActivity,如果有拦截器,就可以把这个过程拦截下来,做一些处理(禁止跳转、修改参数)。

添加拦截器的方法是利用Interceptor注解,实现IInterceptor接口。例如我添加一个拦截器:

//priority 为拦截器的优先级,多个拦截器时候有用
@Interceptor(priority = 8,name = "测试用拦截器")
class TestInterceptor : IInterceptor {override fun init(context: Context?) {// 拦截器的初始化,会在sdk初始化的时候调用该方法,仅会调用一次Log.e("@@","拦截器初始化")}/*** 拦截器的操作* @param postcard 数据* @param callback 回调*/override fun process(postcard: Postcard?, callback: InterceptorCallback?) {if(postcard?.path == "/path/bactivity"){//如果是跳到BActivity,就加个数据postcard.withString("extra", "我是在拦截器中附加的参数")}//继续跳转callback!!.onContinue(postcard)//终止跳转//callback.onInterrupt(null)//抛出异常// callback.onInterrupt(RuntimeException("我觉得有点异常"))// onContinue和onInterrupt至少需要调用其中一种,否则不会继续路由}}

这样子,在BActivity接收的时候,就可以获取到extra,这个key的字符串了

五、 降级策略

什么鬼是降级策略? 因为打开activity是系统级别的操作,我们提交之后了跳转之后,很难插手,所以降级策略其实就是 在跳转过程中,如果出现错误的话,可以进行处理跳转。 方法有两种,一个是处理单词跳转,一个是全局的跳转处理。

方式1: 单个处理-回调方法:

在navigation的时候,添加NavCallback进行回调,回调方法有四个,出现错误的时候,在onLost方法下面处理即可。

ARouter.getInstance().build(intent.data).navigation(this,object: NavCallback() {override fun onArrival(postcard: Postcard?) {//已经打开了目标activityLog.e("@@","目标activity打开完成")finish()}override fun onFound(postcard: Postcard?) {//找到了要打开的activityLog.e("@@","找到了目标activity")}override fun onLost(postcard: Postcard?) {//找不到要打开的activityLog.e("@@","找不到目标activity")}override fun onInterrupt(postcard: Postcard?) {super.onInterrupt(postcard)Log.e("@@","被拦截了")}})

方法2:全局处理-实现接口

如果找不到目标Activity,ARouter默认会提示一个Toast,找不到对象。例如:

    ARouter.getInstance().build("/xxxxx/xxxxx").navigation(this)

这时候如果你要自己全局处理,只需要实现DegradeService接口,并加上一个Path内容任意的注解即可

//path里面的内容可以任意,注意两个斜杠就行
@Route(path = "/cccc/ddd")
class DegradeServiceImpl : DegradeService {//失败的时候处理,注意:如果在navigation时候没有传递context,这个方法的context会是空的override fun onLost(context: Context?, postcard: Postcard?) {Toast.makeText( context,"找不到路径" +postcard?.path ,Toast.LENGTH_SHORT).show()}override fun init(context: Context?) {}}

PS: 不能两种同时使用,单个处理级的方式优先于全局处理,也就是如果同时使用两种方式,只有单独降级能执行。

六、服务管理

这里说的服务不是Android四大组件里面的服务,其实是根据path去获取对象。

例如:首先写一个接口,实现IProvider接口,定义一个方法sayHello

// 声明接口
interface HelloService : IProvider {fun sayHello(name: String)
}

然后写一个实现类,添加注解@Route,path内容不固定:

//实现接口
@Route(path = "/service/hello",name = "测试服务")
class HelloServiceImpl : HelloService {override fun sayHello(name: String){println(name)}override fun init(context: Context?) {}}

然后就可以利用ARouter来调用实现类HelloServiceImpl

//方法1 用类的形式,在navigation方法添加参数
ARouter.getInstance().navigation(HelloService::class.java).sayHello("mike")// 方法2 用path方式,在build添加实现类的Router路径
(ARouter.getInstance().build("/service/hello").navigation() as HelloService).sayHello("tpnet")

还可以利用注入的方式:

class ServiceObj {@JvmField@Autowiredvar helloService: HelloService? = null@JvmField@Autowired(name = "/service/hello")var helloService2: HelloService? = nullinit {ARouter.getInstance().inject(this)}fun testService(){// 1. (推荐)使用依赖注入的方式发现服务,通过注解标注字段,即可使用,无需主动获取helloService?.sayHello("Vergil")// Autowired注解中标注name之后,将会使用byName的方式注入对应的字段,不设置name属性,会默认使用byType的方式发现服务// (当同一接口有多个实现的时候,必须使用byName的方式发现服务)helloService2?.sayHello("Vergil")}}

七、其他使用

当然一个库的功能是很多的,还有其他的使用方面。

获取Fragment实例

在需要获取的Fragment添加注解@Route

@Route(path = "/test/fragment")
public class BlankFragment extends Fragment {}

获取的时候,强制转换。

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

带RequestCode跳转

在navigation方法的第二个参数添加即可:

ARouter.getInstance().build("/test/activity2").navigation(this, 666);

为目标页面声明更多信息

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

@Route(path = "/test/activity", extras = Consts.XXXX)

在拦截器中的process方法,利用getExtra方法即可获取到这个内容。

重写跳转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;    // 按照一定的规则处理之后返回处理后的结果}
}

跳转到其他Module

方法1: 和正常跳转一样,设置path,然后navigation过去

方法2: 指定group分组,例如:

@Route(path = "/path/module",group = "m2")
class ModuleActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_module)}
}

调用则:

    ARouter.getInstance().build("/path/module", "m2").navigation()

PS: 一旦主动指定分组之后,应用内路由需要使用 ARouter.getInstance().build(path, group) 进行跳转,手动指定分组,否则无法找到

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方法中传入当前ActivityARouter.getInstance().build("/test/activity2").withOptionsCompat(compat).navigation();// 使用绿色通道(跳过所有的拦截器)
ARouter.getInstance().build("/home/main").greenChannel().navigation();// 使用自己的日志工具打印日志
ARouter.setLogger();//获取原始的URI
String uriStr = getIntent().getStringExtra(ARouter.RAW_URI);//关闭ARouter
ARouter.getInstance().destroy();

Android跳转-ARouter详细使用教程相关推荐

  1. 使用python玩跳一跳超详细使用教程

    在上一篇文章里介绍了使用Python玩微信跳一跳的详细使用教程,不过依旧还是有很多小伙伴有各种各样的问题.为了让各位小伙伴都能使用黑科技,于是再做一个超详细教程.从Python的安装开始,手把手教你一 ...

  2. python跳一跳教程_使用python玩跳一跳超详细使用教程

    在上一篇文章里介绍了使用Python玩微信跳一跳的详细使用教程,不过依旧还是有很多小伙伴有各种各样的问题.为了让各位小伙伴都能使用黑科技,于是再做一个超详细教程.从Python的安装开始,手把手教你一 ...

  3. HTC Android手机刷机详细全教程

    Android手机有很多定制ROM,看着Android 2.2和Android2.1ROM四处发布,你是否也会心痒痒,想刷机呢.当你想要进行刷机的时候,是否因为复杂的教程和操作命令让你头疼并最终放弃刷 ...

  4. 使用python玩跳一跳超详细使用教程/脚本辅助工具

    本文首发于http://www.52aite.cn博客,没有知乎,没有微信公众号,只是蹭一波python跳一跳的热度. python辅助作者github账号为:wangshub. 作者的知乎专栏为:h ...

  5. android 连接电脑,Android手机连接电脑详细图文教程

    驱动下载: (纳米盘)(备用下载) 本驱动提供XP,Vista系统x86芯片的驱动,其中Vista系统还包括64位系统的专用驱动.针对AMD芯片也给出了专门的驱动,用户可以根据自己的芯片和系统进行选择 ...

  6. Android Studio超级详细安装教程(AMD)

    Android Studio超级详细安装教程(AMD) !!!必看!!! 本教程适合CPU为AMD的计算机使用,如果你的CPU为intel/英特尔请移步至Android Studio超级详细安装教程( ...

  7. Xamarin For Android 打包编译APK文件详细图文教程

    原文链接 本文用于介绍Visual Studio 2012中Xamarin Mono For Android 如何打包编译APK文件,从如何创建Android项目,到如何启动调试,都会逐个配图讲解. ...

  8. 手机APP开发之MIT Appinventor详细实战教程(一),利用通过蓝牙控制单片机,以及实现单片机与android设备之间的串口通信

    目录 (一)前期软件准备和硬件准备 ( 二 ) 实现的思路和操作原理 ( 三) 具体的操作方法 MIT Appinventor 是编程领域较为受欢迎且适用的编程软件 ,因其操作流程和使用方法简单,一直 ...

  9. 台式电脑主板插线步骤图_电脑主板跳线插法 装机接线详细图解教程

    组装一台电脑,主板上的跳线接线是最让小白装机用户头疼的事情,接错了轻则启动不了,重则烧毁硬件,但其实具体跳线插法,在机箱连接的跳线接口上以及主板跳线插座上都有详细标注,我们只需要在主板上找到对应插座, ...

最新文章

  1. MPB:南土所褚海燕组-小麦相关微生物的野外采样与样品保存
  2. Atitit main函数的ast分析  数组参数调用的ast astview解析
  3. 事务处理操作(COMMIT,ROLLBACK)。复制表。更新操作UPDATE实际工作中一般都会有WHERE子句,否则更新全表会影响系统性能引发死机。...
  4. 奥比中光大白(3D结构光)摄像头测试发现对着灯光过曝问题
  5. 常见的正则表达式验证(更新中)
  6. 范醒哲:敬畏自然 渴望技术 —— 新冠肺炎后对网络数据传输能力的思考
  7. 5.1.8 DELETE删除数据
  8. FaceBook ATC 弱网测试工具环境搭建
  9. Oracle数据库的学习
  10. 服务器换主板要重装系统吗,换主板需要重装系统吗【解决方案】
  11. RT-Thread (3) 为RTT增加SP485驱动||RTT UART设备
  12. 抖音去除水印还原真实视频解析
  13. mysql-innodb笔记和Spring的那些事
  14. CAD中图形无法复制,使用块插入来合并两个dwg图形
  15. 【Unity3D】图片纹理压缩方式,干货走起!
  16. 华为2285v2服务器修改SN,华为RH2285 V2服务器升级bios
  17. 镭速发布文件直传新功能,实现端到端快速传输
  18. QPrinter、QPrinterInfo、QPageLayout
  19. Opengl中的三维数学二(点和向量的简单运算)
  20. learnopengl 中 pbr的球体算法

热门文章

  1. 如何利用eclipse创建一个java web项目?
  2. 模拟时钟:时钟根据时间转动
  3. 怎样用电脑收发短信?
  4. 怎么用计算机算出锁屏密码,电脑怎么设置锁屏密码
  5. FIT2CLOUD飞致云发布开源轻量级云管平台CloudExplorer Lite
  6. 微信小程序获取今日天气预报api 免费接口
  7. .vm后缀的文件是什么?
  8. HTML5期末大作业:电影网站设计——电影资讯博客(5页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计 web学生网页设计作业源码
  9. Windows 10 - 安装 Mysql - zip压缩包详细安装教程
  10. 商业调查——您可以下载 16 个免费问卷模板