ARouter使用

 

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lib739449500/article/details/97891938

1.原生跳转实现

  • Google提供的原声路由主要是通过intent,可以分成显示和隐式两种。显示的方案会导致类之间的直接依赖问题,耦合严重;隐式intent需要的配置清单中统一声明,首先有个暴露的问题,另外在多模块开发中协作也比较困难。只要调用startActivity后面的环节我们就无法控制了,在出现错误时无能为力。
  • 传统跳转方式

  1. 第一种,通过intent跳转

  2. 第二种,通过aidl跳转
  3. 第三种,通过scheme协议跳转
  • 为何需要路由
  1. 显示Intent:项目庞大以后,类依赖耦合太大,不适合组件化拆分
  2. 隐式Intent:协作困难,调用时候不知道调什么参数
  3. 每个注册了Scheme的Activity都可以直接打开,有安全风险
  4. AndroidMainfest集中式管理比较臃肿
  5. 无法动态修改路由,如果页面出错,无法动态降级
  6. 无法动态拦截跳转,譬如未登录的情况下,打开登录页面,登录成功后接着打开刚才想打开的页面
  7. H5、Android、iOS地址不一样,不利于统一跳转

2.ARouter使用

2.1 ARouter的优势

  1. 支持直接解析标准URL进行跳转,并自动注入参数到目标页面中
  2. 支持多模块工程使用
  3. 支持添加多个拦截器,自定义拦截顺序
  4. 支持依赖注入,可单独作为依赖注入框架使用
  5. 支持InstantRun
  6. 支持MultiDex(Google方案)
  7. 映射关系按组分类、多级管理,按需初始化
  8. 支持用户指定全局降级与局部降级策略
  9. 页面、拦截器、服务等组件均自动注册到框架
  10. 支持多种方式配置转场动画
  11. 支持获取Fragment
  12. 完全支持Kotlin以及混编(配置见文末 其他#5)
  13. 支持第三方 App 加固(使用 arouter-register 实现自动注册)
  14. 支持生成路由文档
  15. 提供 IDE 插件便捷的关联路径和目标类

 

 

2.2.ARouter的结构

  • ARouter主要由三部分组成,包括对外提供的api调用模块、注解模块以及编译时通过注解生产相关的类模块。
    1. arouter-annotation注解的声明和信息存储类的模块
    2. arouter-compiler编译期解析注解信息并生成相应类以便进行注入的模块
    3. arouter-api核心调用Api功能的模块

2.3ARouter的典型应用

  1. 从外部URL映射到内部页面,以及参数传递与解析
  2. 跨模块页面跳转,模块间解耦
  3. 拦截跳转过程,处理登陆、埋点等逻辑
  4. 跨模块API调用,通过控制反转来做组件解耦

2.4 Arouter引入

以下主要针对下面1.4.1版本使用,不是github最新版本哦。

     2.4.1 添加依赖         

 api "com.alibaba:arouter-api:1.4.1" 

           annotationProcessor "com.alibaba:arouter-compiler:1.2.2"

     2.4.2 添加配置

android {
            defaultConfig {
                ...
                javaCompileOptions {
                    annotationProcessorOptions {
                        arguments = [AROUTER_MODULE_NAME: project.getName()]
                    }
               }
           }
       }

    2.4.3 添加注解

// 在支持路由的页面上添加注解(必选)
// 这里的路径需要注意的是至少需要有两级,/xx/xx
@Route(path = "/test/activity")
 public class YourActivity extend Activity {
    ...
}

2.4.4初始化SDK

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

最好在Application中掉一下destroy方法。解绑,释放资源

@Override
public void onTerminate() {
   Log.d("Application", "onTerminate");
   super.onTerminate();
   ARouter.getInstance().destroy();
}

2.4.5发起路由操作

// 1. 应用内简单的跳转(通过URL跳转在'进阶用法'中)
ARouter.getInstance().build("/test/activity").navigation();

// 2. 跳转并携带参数
ARouter.getInstance().build("/test/1")
            .withLong("key1", 666L)
            .withString("key3", "888")
            .withObject("key4", new Test("Jack", "Rose"))
            .navigation();

2.4.6 添加混淆规则(如果使用了Proguard)

-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep public class com.alibaba.android.arouter.facade.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}

# 如果使用了 byType 的方式获取 Service,需添加下面规则,保护接口
-keep interface * implements com.alibaba.android.arouter.facade.template.IProvider

# 如果使用了 单类注入,即不定义接口实现 IProvider,需添加下面规则,保护实现
# -keep class * implements com.alibaba.android.arouter.facade.template.IProvider
  1.  

2.4.7 使用 Gradle 插件实现路由表的自动加载 (可选)

apply plugin: 'com.alibaba.arouter'

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath "com.alibaba:arouter-register:?"
    }
}

可选使用,通过 ARouter 提供的注册插件进行路由表的自动加载(power by AutoRegister), 默认通过扫描 dex 的方式 进行加载通过 gradle 插件进行自动注册可以缩短初始化时间解决应用加固导致无法直接访问 dex 文件,初始化失败的问题,需要注意的是,该插件必须搭配 api 1.3.0 以上版本使用!

2.4.8 使用 IDE 插件导航到目标类 (可选)

在 Android Studio 插件市场中搜索 ARouter Helper, 或者直接下载文档上方 最新版本 中列出的 arouter-idea-pluginzip 安装包手动安装,安装后 插件无任何设置,可以在跳转代码的行首找到一个图标 (navigation) 点击该图标,即可跳转到标识了代码中路径的目标类

2.4.9 普通跳转还可以通过利用Uri方法:

  Uri uri=Uri.parse("/path/bactivity");
            ARouter.getInstance().build(uri).navigation();

PS: Uri.parse的时候,改为完整路径也是支持的,例如改为val uri = Uri.parse(“tpnet://m.aliyun.com/path/bactivity”),也可以成功跳转到BActivity

 

3.进阶用法

3.1通过URL跳转

Url跳转就是可以根据url来跳转,可以从网页跳到Activity

3.1.1 网页url正常跳转Activity
首先定义一个Activity作为中转,网页的链接都跳到这个Activity,然后再从这个Activity打开网页需要打开的Activity

public class SchameFilterActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Uri uri = getIntent().getData();
        ARouter.getInstance().build(uri).navigation();
        finish();
    }
}

该Activity的manifest为:


            
            
                

                

                
                
            
        

然后定义你要跳转到的Activity,这里定义一个UrlTargetActivity (记得在Manifest说明):


@Route(path = ARouterConstant.ACTIVITY_test_activity1)
public class UrlTargetActivity  extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_url_target);

        TextView tv=findViewById(R.id.textView4);
        tv.setText("当前页面是:"+getLocalClassName());
    }
}

然后在手机打开一个网页,网页内容为:

arouter://m.aliyun.com/test/activity1

点击了这个网页链接之后,就到根据"arouter://m.aliyun.com(scheme://host)跳转到SchemeFilterActivity这个Activity,然后在这个Activity利用ARouter 根据path = test/activity1跳转到UrlTargetActivity

3.2 参数传递

带参数的跳转是很常见的功能,Android可以通过Bundle去传递参数,如果使用ARouter框架,它传递参数通过以下去操作:

    ARouter传递对象的时候,首先该对象需要Parcelable或者Serializable序列化,可能Parcelable这个序列化大家觉得手写起来比较麻烦,但是Android Studio已经有一些插件帮我们自动生成Parcelable序列化了(因为Android用Parcelable序列化优势会更加明显一些)

    字符串、char、int等基本数据类型当然都是可以传递的    当然,它也可以直接传Bundle、数组、列表等很多对象,传递类型如下图

ARouter使用_第1张图片

携带参数的界面跳转,简单使用如下图

ARouter使用_第2张图片

其中,第一个参数代表的是参数的key,第二个参数对应的是我们要传递的属性值,也就是value

那么目标界面如何获取传递过来的值?

这个时候,我们需要在目标界面,使用Autowired注解,

ARouter使用_第3张图片

PS:注意属性名字命名。所以为了规避每一个可能会遇到的风险,建议在@Autowired里面 都写上与之对应具体的key名。

3.3界面跳转动画

直接调用withTransition,里面传入两个动画即可(R.anim.xxx)

ARouter使用_第4张图片

3.4Fragment跳转

Fragment的跳转也可以参照Activity跳转,第一步依旧是先写上类注释,然后是强转,代码如下

3.5声明拦截器(拦截跳转过程,面向切面编程)

拦截器的意思是,例如你想在 AActivity跳到BActivity,如果有拦截器,就可以把这个过程拦截下来,做一些处理(禁止跳转、修改参数)。

拦截器使用和Activity@Route差不多,只不过拦截器是使用另外一个注解@Interceptor。有两个变量,priority是拦截器的优先级,值越小优先级越高,会优先拦截。name是拦截器的名称,开发也不怎么用。

ps:如果两个拦截器的优先级一样,项目编译就会报错。所以,不同拦截器定义的优先级属性值不能相同

添加拦截器的方法是利用Interceptor注解,实现IInterceptor接口。例如我添加一个拦截器:


/ 比较经典的应用就是在跳转过程中处理登陆事件,这样就不需要在目标页重复做登陆检查
// 拦截器会在跳转之间执行,多个拦截器会按优先级顺序依次执行
@Interceptor(priority = 8, name = "测试用拦截器")
public class TestInterceptor implements IInterceptor {
    @Override
    public void init(Context context) {
        // 拦截器的初始化,会在sdk初始化的时候调用该方法,仅会调用一次
        Log.e("arouterinterceptor", "拦截器初始化");
    }

    @Override
    public void process(Postcard postcard, InterceptorCallback callback) {
        if (!TextUtils.isEmpty(postcard.getPath())
                && postcard.getPath().equals("/path/bactivity")) {
            postcard.withString("extra", "我是在拦截器中附加的参数");
        }
        if(callback!=null){
            callback.onContinue(postcard);
        }
        //终止跳转
        //callback.onInterrupt(null)
        //抛出异常
        // callback.onInterrupt(RuntimeException("我觉得有点异常"))
        // onContinue和onInterrupt至少需要调用其中一种,否则不会继续路由

    }

}

在拦截器实现类使用注解@Interceptor会自动注册,就是在编译期间会自动生成映射关系类,使用到的就是APT技术

这里因为是自动注册的,所以可以将不同功能的拦截器放在不同功能的模块中,只有模块被打包到整个项目中,因为自动注册机制所以拦截器就会生效,如果不将这些拦截器放到模块并打包到项目中,那就不会生效,这样就不用去做很多注册与反注册的工作,这也是ARouter适用于模块开发的原因之一。

3.6 ARouter如何实现类似startActivityForResult()?

这种应用场景也是很常见的,那ARouter该如何实现?

第一步:为了方便看效果,我们在第一个Activity设置requestCode 为123,

ARouter使用_第5张图片

onActivityResult

第二步:需要在跳转的navigation方法(这是一个方法重载)里面的第二个参数,设置我们定义的requestCode,(通过匹配requestCode 来实现该功能)

ARouter使用_第6张图片

第三步:在第二个界面的setResult方法里面,写上对应的resultCode,这里就不展示Intent数据了

ARouter使用_第7张图片

综合上面三个步骤,项目编译运行,跳转到第二个界面然后返回上一个界面,日志成功打印:

ARouter使用_第8张图片

 

 

你可能感兴趣的:(2019)