ARouter踩坑指南
Posted xiaoqiang_0719
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ARouter踩坑指南相关的知识,希望对你有一定的参考价值。
文章目录
ARouter踩坑指南
导读
此文章仅记录ARouter使用过程中遇到的坑、理解有误等情况,旨在帮助大家迅速解决问题和理解功能逻辑。
详细使用流程请阅读GitHub源码以及README,地址如下:
添加依赖和配置问题
如果使用kotlin进行开发,有一套基于kotiln的的依赖方式,在app的build.gradle下添加如下代码:
apply plugin: 'kotlin-kapt'
kapt
arguments
arg("AROUTER_MODULE_NAME", project.getName())
dependencies
implementation 'com.alibaba:arouter-api:1.5.2'
kapt 'com.alibaba:arouter-compiler:1.5.2'
...
ARouter Helper插件使用问题
ARouter Helper插件帮助我们建立可视化、可操作的路由跳转,非常好用
但如果使用的AnroidStudio版本是4.1及以上版本,ARouter Helper插件是无法使用的,添加插件之后会出现下面的问题
解决方案可以参考Issues里的临时方案,或者等待开发者发布新版本(目前依然是1.0.0版)
Kotlin中使用注解@Autowired获取参数问题
kotlin中如果要使用@Autowired注解需要注意:
1、变量名称必须要跟传入的key保持一致
2、必须使用@JvmField注解修饰
3、必须使用var来修饰
ARouter.getInstance().build("/xxx/xxx")
.withParcelable("video", video).navigation()
@Autowired
@JvmField
var video: VideoBean? = null
不然报的错误、、、很难分析问题点在哪里,看下面的截图,你咋分析~
Execution failed for task ‘:kaptDebugKotlin’.
A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptWithoutKotlincTask$KaptExecutionWorkAction
java.lang.reflect.InvocationTargetException (no error message)
进阶用法通过URL跳转理解
通过url方式跳转,其他模块不需要了解目标模块的包名等信息即可实现跳转路由,可充分解耦
- 当前Activity通过Scheme方式跳转目标Activity,注意url的参数需与目标Activity在androidManifest注册的host和scheme保持一致
- 新建一个Activity用于监听Scheme事件,之后直接把url传递给ARouter即可
//当前Activity调用Intent跳转 host=www.nobo.com,scheme=wilfried,路由路径为/url/main
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("wilfried://www.nobo.com/url/main")))
<!-- AndroidManifest注册SchemeFilterActivity用于中转操作-->
<activity android:name=".url.SchemeFilterActivity">
<intent-filter>
<data
android:host="www.nobo.com"
android:scheme="wilfried"/>
<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可获取到uri进行使用uri的方式进行跳转,通过NavCallback关闭中转Activity
class SchemeFilterActivity : Activity()
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
val uri = intent.data
Log.i(TAG, "SchemeFilterActivity: $uri")
ARouter.getInstance().build(uri).navigation(this, object : NavCallback()
override fun onArrival(postcard: Postcard)
finish()
)
使用withObject传递参数
ARouter支持使用withParcelable、withSerializable和withObject来传递对象,前两者需要类是实现Parcelable或者是实现Serializable的,但是withObject不需要实现任何序列化,他需要使用json2Object、object2Json方式来支持,所以我们必选要实现一个实现了SerializationService的类
/**
* 如果跳转的时候需要传递类,需要添加如下类,使用@Route注解修饰
*/
@Route(path = "/yourservicegroupname/json")
class JsonServiceImpl : SerializationService
override fun init(context: Context?)
override fun <T> json2Object(text: String?, clazz: Class<T>?): T
return JSON.parseObject(text, clazz)
override fun object2Json(instance: Any?): String
return JSON.toJSONString(instance)
override fun <T> parseObject(input: String?, clazz: Type?): T
return JSON.parseObject(input, clazz)
拦截器理解
我们使用实现IInterceptor重写process的方式可以实现一个ARouter拦截器,任何路由都会经过拦截器(可以使用绿色通过ARouter.getInstance().build("/home/main").greenChannel().navigation()来跳过拦截器)
实现拦截器之后,不论是否要拦截一定要回调callback.onContinue(postcard)或者callback.onInterrupt(null)。如果我们在路由之前设置了路由状态的监听,那则分别会回调 onArrival,onInterrupt,此处可以来对跳转成功或被拦截做相应操作
//此拦截器未进行任何拦截,仅打印量下log,如果未调用onContinue或者onInterrupt则路由不会成功,排查问题还不好排查,尤其注意下。process可根据patch拦截固定路由
class TestInterceptor : IInterceptor
override fun init(context: Context?)
Log.i(TAG, "TestInterceptor init ")
override fun process(postcard: Postcard?, callback: InterceptorCallback?)
Log.i(TAG, "TestInterceptor init $postcard?.path")
callback?.onContinue(postcard)
发起路由的Activity,是否被拦截会分别调用onArrival、onInterrupt
ARouter.getInstance()
.build("/test/activity4")
.navigation(this, new NavCallback()
@Override
public void onArrival(Postcard postcard)
Log.d("ARouter", "通过");
@Override
public void onInterrupt(Postcard postcard)
Log.d("ARouter", "被拦截了");
);
全局降级和单独降级
对于降级的理解,其实就是路由跳转失败之后会调用onLost回调来给出一个路由失败策略,而全局降级则是会给出一个统一的策略,单独降级则需要在navigation时单独处理onLost回调
- 定义全局降级
//实现DegradeService接口,并加上一个 **Path内容任意** 的注解
@Route(path = "/xxx/xxx")
class GlobalDegradeService : DegradeService
override fun init(context: Context?)
Log.i(TAG, "GlobalDegradeService init: ")
override fun onLost(context: Context?, postcard: Postcard?)
Log.i(TAG, "GlobalDegradeService 全局降级: ")
- 定义单独降级
ARouter.getInstance().build("/main/main2")
.navigation(this, object :
NavCallback()
override fun onLost(postcard: Postcard?)
Log.i(TAG, "onLost: 单独降级 ")
override fun onArrival(postcard: Postcard?)
Log.i(TAG, "onArrival: ")
)
注意:抽象类 NavCallback实现了NavigationCallback,所以我们可以只实现部分我们关心的方法,onArrival方法仍为抽象方法,必须实现
public abstract class NavCallback implements NavigationCallback
@Override
public void onFound(Postcard postcard)
// Do nothing
@Override
public void onLost(Postcard postcard)
// Do nothing
@Override
public abstract void onArrival(Postcard postcard);
@Override
public void onInterrupt(Postcard postcard)
// Do nothing
实现onActivityResult路由
使用带返回值方式进行路由,navigation方法提供了使用requestCode参数的构造方法,我们可以使用此构造方法来进行路由,然后重写onActivityResult方法, 但是requestCode的值不能小于0否则不会回调onActivityResult方法(源码中判断requestCode>=0),并且根据log很难排查 ,此处需特别注意
ARouter.getInstance()
.build("/test/activity2")
.navigation(this, -1);//不会回调onActivityResult
以上是关于ARouter踩坑指南的主要内容,如果未能解决你的问题,请参考以下文章