ARouter路由的详细使用

一.ARouter是什么

ARouter是由阿里推出的一款页面路由框架,主要用于组件化开发过程中,组件之间页面的跳转和通信,确保组件之间没有相互依赖,也能进行跳转

二.为什么要使用ARouter

Android原始的页面跳转最常用到的是显示Intent和隐式Intent跳转方式

显示Intent跳转:

Intent intent = new Intent(this,XXXActivity.class);

startActivity(intent);

缺点:由于需要直接持有对应class,从而导致了强依赖关系,提高了耦合度

隐式Intent跳转:

Intent intent = new Intent();

intent.setAction(“com.android.activity.MY_ACTION”);

startActivity(intent);

缺点:action等属性的定义在Manifest,导致了扩展性较差,规则集中式管理,导致协作变得非常困难。

使用原生Intent跳转时,跳转的过程开发者无法干预,一些埋点,登录判断等通用的逻辑操作比较难实现,不可能再每一个页面去单独判断,我们的目标是在页面跳转的过程统一去判断,而原生的跳转方式无法实现,所以才有了ARouter页面路由。

ARouter页面路由可以解决的问题:

1.可以实现多个组件之间的跳转,确保各个组件之间相互独立,互不依赖

2.可以实现自动注册(只要添加了相关注解,就可以实现自动注册到ARouter框架)

3.可以知晓页面跳转的过程,对跳转的过程进行监听(降级策略)

4.可以对页面跳转进行拦截(登录判断,埋点)

5.支持InstantRun

6.可以直接解析标准URL进行跳转,并自动注入参数到目标页面中

7.可以通过控制反转来做组件解耦(IProvider)

ARouter典型的应用场景:

1.从外部URL映射到内部页面,以及参数传递与解析

2.跨模块页面跳转,模块间解耦

3.拦截跳转过程,处理登陆、埋点等逻辑

4.跨模块API调用,通过控制反转来做组件解耦

三.ARouter怎么用

1.框架依赖

在项目的build.gradle中defaultConfig闭包中添加

 javaCompileOptions {
            annotationProcessorOptions {
                arguments = [moduleName: project.getName()]
            }
        }

在dependencies中添加

 // 替换成最新版本, 需要注意的是api
    // 要与compiler匹配使用,均使用最新版可以保证兼容
    implementation 'com.alibaba:arouter-api:1.3.1'
    annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'

2.在Application中初始化ARouter

 @Override
    public void onCreate() {
        super.onCreate();
        if (BuildConfig.DEBUG) {    // 这两行必须写在init之前,否则这些配置在init过程中将无效
            ARouter.openLog();     // 打印日志
            ARouter.openDebug();   // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
        }
        ARouter.init(this); // 尽可能早,推荐在Application中初始化
    }

3.常用的功能:

3.1.普通不带参数的页面跳转(等价于startActivity())

目标Activity:添加@Router注解,定义唯一识别的路劲path,path路劲必须两级目录以上("/xx/xx")

跳转的页面:通过ARouter进行跳转

 ARouter.getInstance().build("/ac/second").navigation();

3.2.普通携带参数的页面跳转

目标Activity:通过@Router注解,接收参数的方式有两种

1.通过Intent获取

2.通过注解方式获取,使用@Autowired注解变量,并在onCreat()中添加注入(注入可以放在BaseActivity中)

注意:通过注解方式获取参数,定义参数变量时,不能用private私有属性

执行跳转的页面:通过调用withString(key,value)等api进行传参

 ARouter.getInstance().build("/ac/second")
                        .withString("name","我是传递的参数")
                        .navigation();

3.3.普通带请求码的页面跳转(等价于startActivityForResult)

目标Activity:跟上面的都一样

执行跳转的Activity:在navigation()方法中传入请求码即可

注意:如果请求码为0时,是没有startActivityForResult功能

 ARouter.getInstance().build("/ac/second").navigation(MainActivity.this,10);

3.4.普通携带自定义对象的页面跳转--SerializationService

这里所谓的自定义对象指的是对象的自动转换,比如说,AActivity跳转到BActivity时,AActivity携带了一个json字符串,但是我希望在BActivity接收参数的时候,是接收json解析后的对象如User对象,相反也是如此(AActivity携带User对象,BActivity接收参数时,是接收User转成json后的字符串),也就是说转化的过程是在跳转的过程中进行的。

首先定义一个类实现SerializationService,重写里面的方法,定义Gson解析对象

其次在目标Activity中接收参数,接收的是json字符串

最后在跳转的地方传递参数

即,传递的是User对象,但接收的是User对象对应的json字符串,这个转换的过程是在页面跳转时,由ARouter框架自行调用

3.5.通过URL不携带参数跳转页面

通过uri跳转的方式,类似采用Scheme协议跳转,在目标Activity的清单文件中定义指定的scheme,host,path等属性,然后拼接成一个uri对象,就可以跳转到指定的Activity,但是采用之前的方法,我们必须在每一个目标Activity清单中都定义scheme相关参数,要是需要跳转的Activity数量比较多的话,那整个清单文件就会显得比较臃肿,维护起来比较麻烦。但是ARouter框架可以直接通过uri进行跳转,这给了我们一个统一处理的方式。我们可以在项目中创建一个统一处理Scheme跳转的SchemeActivity作为中转,该Activity不需要布局文件,然后在清单中为该Activity定义scheme和host,如果外部需要跳转时,就采用统一的scheme和host,然后再拼接目标Activity的路劲,这样就可以在新建的SchemeActivity中统一通过ARouter传入接收的uri,进行跳转到指定的Activity。以下时具体的步骤

首先,创建一个统一管理Scheme协议跳转的页面SchemeActivity作为中转,将收到的uri通过ARouter进行跳转

清单中指定公共的scheme和host

其次,在目标Activity中添加@Router注解,添加页面路劲

最后,在调用的地方,采用Scheme协议进行跳转,要采用公共的scheme和host,确保每一个uri的跳转都会先到达中转Activity中。

 String url = "common://com.my.app/ac/login";
 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
 startActivity(intent);

3.6.通过URL携带参数跳转页面

原理同3.5,只是在执行跳转的时候,在url末尾添加要传递的参数,在目标Activity定义要接收的参数

在目标Activity:

在跳转url后面拼接参数

 String url = "common://com.my.app/ac/login?name=我是Scheme跳转&age=20";
 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
 startActivity(intent);

3.7.添加自定义拦截器

所谓的拦截器,是指在页面跳转前进行拦截,因此,可以在拦截器里面做一些通用的逻辑判断,比如,目标页面是否需要登录的判断,之前的做法是,在每一个目标页面启动的时候各自进行是否登录的判断,这样做工作量多不说,也不好统一去管理,采用ARouter的自定义拦截器,我们就可以方便的在拦截器中获取目标界面是否需要登录,如果需要登录,则拦截此次的跳转,直接跳转到登录页面,如果目标页面不需要登录,则不拦截,进行正常流程的页面跳转。也可以在拦截器中对目标界面的一些参数进行修改,重新赋值(postCard)

首先定义一个类,实现IInteceptor,在process()方法中获取目标Activity中添加的属性extras属性值,用于判断目标Activity是否需要登录才可以使用

//继续跳转
callback!!.onContinue(postcard)

//终止跳转
//callback.onInterrupt(null)

//抛出异常
// callback.onInterrupt(RuntimeException("我觉得有点异常")),会在降级策略中的回调返回

说明:

1.需要用@Inteceptor添加注解,添加属性priopity,拦截器的优先级,当同时添加多个拦截器时,拦截器的执行顺序时按照该值指定的优先级触发

2.回调方法callback.onContinue(postcard)和callback.onInterrupt(null)必须调用其中一个,否则路由无法继续

3.如果需要在拦截器中添加Toast提示,需要切换到主线程(拦截器是运行在ARouter开启的子线程中)

 Handler mainHandler = new Handler(Looper.getMainLooper());
        mainHandler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(mContext,"制行拦截器",Toast.LENGTH_SHORT).show();
                //已在主线程中,更新UI
            }
        });

其次,在每一个目标Activity中都添加extras属性,用来标识当前页面是否需要登录

说明:extras属性是一个int类型的值,表明该值有32位,32个二进制位,每一位二进制都可以代表一个开关,也就是说可以同时为一个目标Activity添加32个开关标识位

3.8.降级策略

所谓的降级策略,其实指的就是在界面跳转的过程中,我们可以知道其具体的状态,方便我们进行一些操作,比如说跳转完成,跳转失败,传入的路劲时错误的(页面找不到)和页面找到等四种状态,我们就可以方便的在页面跳转失败的时候,给出具体的提示或者操作。降级策略又分为单一策略全局策略。

单一策略:针对单个页面跳转有效,采用回调的方式获取状态,navigation()第二个参数可以传入一个回调,可以在回调中去处理自己想要的逻辑

全局策略:针对所有的页面跳转都起作用(类似修改统一的页面找不到提示语)

单一策略和全局策略可以同时使用,但是两种同时使用时,单一策略的优先级比较高,全局策略的会被覆盖

3.9.跨模块Api调用(暴露服务)

所谓跨模块Api调用,比如,现在有两个模块ModuleA和ModuleB,ModuleB中有一个方法show(),假如ModuleA中想要调用ModuleB中的show()方法,那该怎么实现呢?

因为ModuleA和ModuleB两者没有相互依赖,按照原生的方法很难实现直接跨模块调用api,而ARouter框架里面就可以方便实现,通过给ModuleB暴露一个服务(此服务并不是Android中的服务,而是一个接口),将需要被调用的方法定义在该服务中,这样ModuleA中就可以通过该接口,调用里面定义的方法。

首先,在ModuleB中创建一个服务(暴露一个接口),将需要被调用的方法定义在该接口中,添加@Router注解

其次,在ModuleA中需要调用的地方去获取该服务对象,即可调用里面定义的方法,获取服务对象的方法有三种

1.通过调用ARouter.getInstance().build("/ac/service").navigation();然后强制转成指定的服务对象

CustomService customService = (CustomService) ARouter.getInstance().build("/ac/service").navigation();
customService.showToast(MainActivity.this,"测试而已");

2.通过调用ARouter.getInstance().navigation(CustomService.class);navigation中传入指定服务对象

 CustomService customService = ARouter.getInstance().navigation(CustomService.class);
 customService.showToast(MainActivity.this,"我的hi");

3.采用注解的方式获取服务对象,跟接收普通参数一样用@Autowired注解,传去服务的路劲path

@Autowired(name = "/ac/service")
protected CustomService customService;

 

3.10.添加页面跳转动画

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

兼容跳转:

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();
}

 

3.11.获取Fragment片段对象

首次创建一个片段,并为片段添加@Router注解,添加路劲path

其次,在需要获取片段对象的地方调用以下代码

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

说明:如果build(path)中的path对应的是一个Activity,则调用navigation()后,是进行跳转的作用,如果path对应的是一个普通的类或者Fragment时,则调用navigation()后,是获取该类的对象,可以通过强制转成指定的类对象即可。

4.详细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方法中传入当前Activity

ARouter.getInstance()
    .build("/test/activity2")
    .withOptionsCompat(compat)
    .navigation();
        
// 使用绿色通道(跳过所有的拦截器)
ARouter.getInstance().build("/home/main").greenChannel().navigation();

// 使用自己的日志工具打印日志
ARouter.setLogger();

// 使用自己提供的线程池
ARouter.setExecutor();

有了ARouter页面路由的基础,我们就可以进行组件化开发了,下一篇文章专门来讲解如何使用ARouter进行组件化开发

发布了14 篇原创文章 · 获赞 16 · 访问量 473

猜你喜欢

转载自blog.csdn.net/huyinda/article/details/104569796