通过URL跳转
//亲测:可以直接打开其他APP的页面,前提是这个“其他APP”是已经存活在系统中
"ARouter 路由跳转:使用URL的方式1 (携带intent参数)" -> {
val bundle = Bundle()
bundle.putString("bundleStringKey", "bundleStringValue")
ARouter.getInstance()
.build(ARouterConstant.App.WEBVIEW_ACTIVITY)
.withString("url", "file:///android_asset/www/arouter-test.html")
.withInt("intKey", 100)
.withBoolean("booleanKey", true)
.withBundle("bundle", bundle)
.navigation()
}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
</head>
<body>
<center>
<h2>ARouter 测试</h2>
</center>
<p><a href="arouter://m.knowledge.com/app/test01">arouter://m.knowledge.com/app/test01</a></p>
<p><a href="arouter://m.knowledge.com/app/webview?url=https%3a%2f%2fm.abc.com%3fa%3db%26c%3dd">测试URL Encode情况</a></p>
<p><a href="arouter://m.knowledge.com/app/test02?name=alex&age=18&obj=%7b%22sex%22%3a%22jack%22%2c%22id%22%3a666%7d">"ARouter 路由跳转:使用URL的方式2 (携带intent参数):通过注解的方式获取参数":arouter:/m.knowledge.com/app/test02?name=alex&age=18&obj={"sex":"jack","id":"666"}</a></p>
<p><a href="http://m.knowledge.com/app/test01">http://m.knowledge.com/app/test01</a></p>
</body>
</html>
startActivityForResult
"ARouter 路由跳转:startActivityForResult" -> {
ARouter.getInstance()
.build(ARouterConstant.App.TEST_01_SCHEME_FILTER_ACTIVITY)
.navigation(mContext as Activity, 666)
}
动画
//转场动画(常规方式)
"ARouter 路由:旧版本转场动画" -> {
ARouter.getInstance()
.build(ARouterConstant.App.TEST_01_SCHEME_FILTER_ACTIVITY)
.withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)
.navigation(this.mContext)
}
//转场动画(API16+)
"ARouter 路由:新版本转场动画" -> {
if (Build.VERSION.SDK_INT >= 16) {
val compat: ActivityOptionsCompat =
ActivityOptionsCompat.makeScaleUpAnimation(
it,
it.width / 2,
it.height / 2,
0,
0
)
ARouter.getInstance()
.build(ARouterConstant.App.TEST_01_SCHEME_FILTER_ACTIVITY)
.withOptionsCompat(compat)
.navigation()
} else {
Toast.makeText(
this.mContext,
"API < 16,不支持新版本动画",
Toast.LENGTH_SHORT
).show()
}
}
获取Fragment
"ARouter 路由:获取Fragment" -> {
val fragment: Fragment = ARouter.getInstance().build(ARouterConstant.App.TEST_03_SIMPLE_FRAGMENT)
.withString("name", "老王")
.withInt("age", 18)
.withBoolean("boy", true)
.withLong("high", 180)
.withString("url", "https://a.b.c")
.navigation() as Fragment
Toast.makeText(
this.mContext,
"找到Fragment:$fragment",
Toast.LENGTH_SHORT
).show()
}
拦截器
//注意:只要有一处地方对这个路径设置了拦截器,其他地方调用的时候也会受到影响
//对于拦截器的 priority 属性,值越小,优先级越高,并且需要注意,该属性的值不能设置为相同的,否则编译时会直接报错。
"ARouter 路由:拦截器测试"-> {
ARouter.getInstance()
.build(ARouterConstant.App.TEST_02_SCHEME_FILTER_ACTIVITY)
.navigation(this.mContext, object : NavCallback() {
override fun onArrival(postcard: Postcard) {
Log.d("ARouter", "到达终点,欧耶!")
}
override fun onInterrupt(postcard: Postcard) {
Log.d("ARouter", "被拦截了")
}
})
}
ARouter拦截器的用途举例:实现登录拦截
NavCallback回调
"ARouter 路由:跳转失败,单独降级" -> {
ARouter.getInstance().build("/xxx/xxx")
.navigation(this.mContext, object : NavCallback() {
override fun onFound(postcard: Postcard) {
Log.d("ARouter", "找到了")
}
override fun onLost(postcard: Postcard) {
Log.d("ARouter", "找不到了")
}
override fun onArrival(postcard: Postcard) {
Log.d("ARouter", "跳转完了")
}
override fun onInterrupt(postcard: Postcard) {
Log.d("ARouter", "被拦截了")
}
})
}
服务单类方法的调用的几种方式:
"ARouter 路由:调用单类" -> {
ARouter.getInstance().navigation(SingleService::class.java).sayHello("Knowledge Pooling")
}
"ARouter 路由:ByName调用服务" -> {
(ARouter.getInstance().build("/yourservicegroupname/hello")
.navigation() as HelloService).sayHello("Knowledge Pooling")
}
"ARouter 路由:ByType调用服务" -> {
ARouter.getInstance().navigation(HelloService::class.java).sayHello("Knowledge Pooling")
}
拦截器和服务的异同:
拦截器和服务所需要实现的接口不同,但是结构类似,都存在 init(Context context) 方法,但是两者的调用时机不同
拦截器因为其特殊性,会被任何一次路由所触发,拦截器会在ARouter初始化的时候异步初始化,如果第一次路由的时候拦截器还没有初始化结束,路由会等待,直到初始化完成。
服务没有该限制,某一服务可能在App整个生命周期中都不会用到,所以服务只有被调用的时候才会触发初始化操作
为目标页面声明更多信息
// 我们经常需要在目标页面中配置一些属性,比方说"是否需要登陆"之类的
// 可以通过 Route 注解中的 extras
属性进行扩展,这个属性是一个 int值,换句话说,单个int有4字节,也就是32位,可以配置32个开关
// 剩下的可以自行发挥,通过字节操作可以标识32个开关,通过开关标记目标页面的一些属性,在拦截器中可以拿到这个标记进行业务逻辑判断
@Route(path = “/test/activity”, extras = Consts.XXXX)
自动注入 @Autowired(name = “name”)遇到的坑:
注意:需要设置访问权限为public 否则编译的时候会报这个错误:ARouter::Compiler An exception is
encountered, [The inject fields CAN NOT BE ‘private’!!! please check
field [name] in class … 意思是:编译器遇到异常, 注入字段不能为“私有”!!!请在课堂上检查字段[name]
目前是直接换成使用java。而找到了一种解决方法是:Kotlin类中的字段无法注入如何解决?
首先,Kotlin中的字段是可以自动注入的,但是注入代码为了减少反射,使用的字段赋值的方式来注入的,Kotlin默认会生成set/get方法,并把属性设置为private
所以只要保证Kotlin中字段可见性不是private即可,简单解决可以在字段上添加 @JvmField。
//如果需要自动装配参数,需要进行Arouter 注入
// 之后,ARouter会自动对字段进行赋值,无需主动获取
ARouter.getInstance().inject(this);
参数细节:
使用 withObject 传递 List 和 Map 的实现了Serializable 接口的实现类(ArrayList/HashMap)的时候,接收该对象的地方不能标注具体的实现类类型应仅标注为 List 或 Map,否则会影响序列化中类型的判断, 其他类似情况需要同样处理。
// 如果需要传递自定义对象,新建一个类(并非自定义对象类),然后实现 SerializationService,并使用@Route注解标注(方便用户自行选择序列化方式),例如:
@Route(path = "/yourservicegroupname/json")
public class JsonServiceImpl implements SerializationService {
@Override
public void init(Context context) {
}
@Override
public <T> T json2Object(String text, Class<T> clazz) {
return JSON.parseObject(text, clazz);
}
@Override
public String object2Json(Object instance) {
return JSON.toJSONString(instance);
}
@Override
public <T> T parseObject(String input, Type clazz) {
return null;
}
}
传递自定义对象
// 如果需要传递自定义对象,新建一个类(并非自定义对象类),然后实现 SerializationService,并使用@Route注解标注(方便用户自行选择序列化方式),例如:
@Route(path = "/yourservicegroupname/json")
public class JsonServiceImpl implements SerializationService {
@Override
public void init(Context context) {
}
@Override
public <T> T json2Object(String text, Class<T> clazz) {
return JSON.parseObject(text, clazz);
}
@Override
public String object2Json(Object instance) {
return JSON.toJSONString(instance);
}
@Override
public <T> T parseObject(String input, Type clazz) {
return null;
}
}
获取携带的参数的方法
方法一:intent.getStringExtra()诸如此类(因此,也可以传递Parcelable或者Serializable序列化的参数)。
方法二:使用注解。
注意: URL中不能传递Parcelable类型数据,通过ARouter api可以传递Parcelable对象