Android跳转-ARouter详细使用教程
一、简介
Android平台中对页面、服务提供路由功能(跳转)的一个库
1.1 最新版本
模块 | arouter-api | arouter-compiler | arouter-annotation |
---|---|---|---|
最新版本 |
1.2 实例图片
1.3 功能介绍
- 支持直接解析标准URL进行跳转,并自动注入参数到目标页面中
- 支持多模块工程使用
- 支持添加多个拦截器,自定义拦截顺序
- 支持依赖注入,可单独作为依赖注入框架使用
- 支持InstantRun
- 支持MultiDex(Google方案)
- 映射关系按组分类、多级管理,按需初始化
- 支持用户指定全局降级与局部降级策略
- 页面、拦截器、服务等组件均自动注册到框架
- 支持多种方式配置转场动画
- 支持获取Fragment
- 完全支持Kotlin以及混编(配置见文末 其他#5)
1.4 应用场景
- 从外部URL映射到内部页面,以及参数传递与解析
- 跨模块页面跳转,模块间解耦
- 拦截跳转过程,处理登陆、埋点等逻辑
- 跨模块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详细使用教程相关推荐
- 使用python玩跳一跳超详细使用教程
在上一篇文章里介绍了使用Python玩微信跳一跳的详细使用教程,不过依旧还是有很多小伙伴有各种各样的问题.为了让各位小伙伴都能使用黑科技,于是再做一个超详细教程.从Python的安装开始,手把手教你一 ...
- python跳一跳教程_使用python玩跳一跳超详细使用教程
在上一篇文章里介绍了使用Python玩微信跳一跳的详细使用教程,不过依旧还是有很多小伙伴有各种各样的问题.为了让各位小伙伴都能使用黑科技,于是再做一个超详细教程.从Python的安装开始,手把手教你一 ...
- HTC Android手机刷机详细全教程
Android手机有很多定制ROM,看着Android 2.2和Android2.1ROM四处发布,你是否也会心痒痒,想刷机呢.当你想要进行刷机的时候,是否因为复杂的教程和操作命令让你头疼并最终放弃刷 ...
- 使用python玩跳一跳超详细使用教程/脚本辅助工具
本文首发于http://www.52aite.cn博客,没有知乎,没有微信公众号,只是蹭一波python跳一跳的热度. python辅助作者github账号为:wangshub. 作者的知乎专栏为:h ...
- android 连接电脑,Android手机连接电脑详细图文教程
驱动下载: (纳米盘)(备用下载) 本驱动提供XP,Vista系统x86芯片的驱动,其中Vista系统还包括64位系统的专用驱动.针对AMD芯片也给出了专门的驱动,用户可以根据自己的芯片和系统进行选择 ...
- Android Studio超级详细安装教程(AMD)
Android Studio超级详细安装教程(AMD) !!!必看!!! 本教程适合CPU为AMD的计算机使用,如果你的CPU为intel/英特尔请移步至Android Studio超级详细安装教程( ...
- Xamarin For Android 打包编译APK文件详细图文教程
原文链接 本文用于介绍Visual Studio 2012中Xamarin Mono For Android 如何打包编译APK文件,从如何创建Android项目,到如何启动调试,都会逐个配图讲解. ...
- 手机APP开发之MIT Appinventor详细实战教程(一),利用通过蓝牙控制单片机,以及实现单片机与android设备之间的串口通信
目录 (一)前期软件准备和硬件准备 ( 二 ) 实现的思路和操作原理 ( 三) 具体的操作方法 MIT Appinventor 是编程领域较为受欢迎且适用的编程软件 ,因其操作流程和使用方法简单,一直 ...
- 台式电脑主板插线步骤图_电脑主板跳线插法 装机接线详细图解教程
组装一台电脑,主板上的跳线接线是最让小白装机用户头疼的事情,接错了轻则启动不了,重则烧毁硬件,但其实具体跳线插法,在机箱连接的跳线接口上以及主板跳线插座上都有详细标注,我们只需要在主板上找到对应插座, ...
最新文章
- MPB:南土所褚海燕组-小麦相关微生物的野外采样与样品保存
- Atitit main函数的ast分析 数组参数调用的ast astview解析
- 事务处理操作(COMMIT,ROLLBACK)。复制表。更新操作UPDATE实际工作中一般都会有WHERE子句,否则更新全表会影响系统性能引发死机。...
- 奥比中光大白(3D结构光)摄像头测试发现对着灯光过曝问题
- 常见的正则表达式验证(更新中)
- 范醒哲:敬畏自然 渴望技术 —— 新冠肺炎后对网络数据传输能力的思考
- 5.1.8 DELETE删除数据
- FaceBook ATC 弱网测试工具环境搭建
- Oracle数据库的学习
- 服务器换主板要重装系统吗,换主板需要重装系统吗【解决方案】
- RT-Thread (3) 为RTT增加SP485驱动||RTT UART设备
- 抖音去除水印还原真实视频解析
- mysql-innodb笔记和Spring的那些事
- CAD中图形无法复制,使用块插入来合并两个dwg图形
- 【Unity3D】图片纹理压缩方式,干货走起!
- 华为2285v2服务器修改SN,华为RH2285 V2服务器升级bios
- 镭速发布文件直传新功能,实现端到端快速传输
- QPrinter、QPrinterInfo、QPageLayout
- Opengl中的三维数学二(点和向量的简单运算)
- learnopengl 中 pbr的球体算法
热门文章
- 如何利用eclipse创建一个java web项目?
- 模拟时钟:时钟根据时间转动
- 怎样用电脑收发短信?
- 怎么用计算机算出锁屏密码,电脑怎么设置锁屏密码
- FIT2CLOUD飞致云发布开源轻量级云管平台CloudExplorer Lite
- 微信小程序获取今日天气预报api 免费接口
- .vm后缀的文件是什么?
- HTML5期末大作业:电影网站设计——电影资讯博客(5页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计 web学生网页设计作业源码
- Windows 10 - 安装 Mysql - zip压缩包详细安装教程
- 商业调查——您可以下载 16 个免费问卷模板