ARouter踩坑指南

Posted xiaoqiang_0719

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ARouter踩坑指南相关的知识,希望对你有一定的参考价值。

ARouter踩坑指南

导读

此文章仅记录ARouter使用过程中遇到的坑、理解有误等情况,旨在帮助大家迅速解决问题和理解功能逻辑。

详细使用流程请阅读GitHub源码以及README,地址如下:

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版)

在这里插入图片描述

进阶用法通过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踩坑指南的主要内容,如果未能解决你的问题,请参考以下文章

ARouter踩坑指南

ARouter踩坑指南

ARouter原理解析之仿ARouter自定义路由框架

xStream.jar踩坑指南

Java URL类踩坑指南

centos部署flask+nginx+uwsgi之踩坑指南