3

Android 阿里路由框架ARouter

一:前言
随着项目越来越大,有的项目已经超过100M,就会带来很多问题,随着代码量的增加,AS编译时间增加,代码的耦合性增加,Android组件化能很好的解决这2点问题,组件化带来问题,我们如何解决组件的通讯问题,组件间的页面调用问题等问题,阿里路由ARouter提供了一个很好解决方案
二:ARouter使用
1.添加依赖:
第一步:在基础的moudle_base库中添加

dependencies {
    compile 'com.alibaba:arouter-api:1.5.0'
    annotationProcessor 'com.alibaba:arouter-compiler:1.2.2'
    }

第二步:在业务组件中例如:moudle_login等模块中添加

dependencies {
    annotationProcessor 'com.alibaba:arouter-compiler:1.2.2'
    }

第三步:在模块中build.gradle下的android的defaultConfig配置

android{
defaultConfig {
 //Arouter路由配置,第三步配置信息
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
                includeCompileClasspath = true
            }
        }
        
        }
        }

2.在App模块中Application中初始化ARouter

 private void initRouter() {
        //这两行必须写在init之前,否则这些配置在init过程中无效
        if (AppUtils.isAppDebug()) {//第三方工具判断是否是Debug 或者BuildConfig.DEBUG
            //打印日志
            ARouter.openLog();
            //开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
            ARouter.openDebug();

        }
        ARouter.init(mApplication);

    }

3.流程分析
界面跳转到B界面,arouter做了以下工作:
image.png
从上图流程中,我们可以发现Arouter中原理:
1.通过apt技术利用注解编译时生成类,封装目标界面类的类信息。
2.在初始化时,把编译生成的类通过key-value的方式存储在arouter中。
3.发送操作者通过key获取到目标界面类的信息。
4.把发送操作者的信息与目标界面类信息进行结合或者关联在一起。
5.实现跳转功能。
其实简单概括:将需要相互跳转的界面信息传递至arouter中存储关联 & 实现跳转。

4.路由使用
4.1跳转页面不带参
发送跳转操作

// 1. 普通跳转
ARouter.getInstance().build("/test/LoginActivity").navigation();

目标页面

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

我们定义一个RouterUtils工具类来统一管理这些路由跳转路径path

public class RouterUtils {
    /**
     * 定义一个RouterUtils工具类
     */
    //定义一个Group,ARouter路由第一个层级代表一个组别
    public static final String LOGIN_GROUP = "/login";
    public static final String LoginActivity=LOGIN_GROUP+"/LoginActivity";
    public static final String WebViewActivity=LOGIN_GROUP+"/WebViewActivity";
}

5.2跳转界面带参数
image.png
发送跳转

ARouter.getInstance().build(RouterUtils.WebViewActivity).withString("url", getString(R.string.help_center)).navigation();

目标页面

@Route(path = RouterUtils.WebViewActivity)
public class WebViewActivity extends BaseActivity {
//获取数据三种方式
    //1.通过Autowired注解表明key   &  需要在onCreate中调用ARouter.getInstance().inject(this);配合使用
    @Autowired(name = "key1")
    public long data;
    //2.通过Autowired注解 & 将key1作为属性的名称   &  需要在onCreate中调用ARouter.getInstance().inject(this);配合使用
    @Autowired()
    public long key1;
    //前两种没怎么用过
//3.获取数据,通过Bundle
 String url=getIntent().getStringExtra("url");
        LogUtils.d("initData: url=" + url);
}

5.3 Uri跳转
界面配置

<activity android:name=".activity.SchameFilterActivity">
    <!-- Schame -->
    <intent-filter>
        <data
        android:host="m.aliyun.com"
        android:scheme="arouter"/>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
    </intent-filter>
</activity

发送跳转操作

Uri testUriMix = Uri.parse("arouter://m.aliyun.com/test/activity2");
                ARouter.getInstance().build(testUriMix)
                        .withString("key1", "value1")
                        .navigation();

目标页面

@Route(path = "/test/activity2")
public class Test2Activity extends AppCompatActivity {
}

5.4跳转页面结果监听

ARouter.getInstance()
              .build("/test/activity2")
              .navigation(this, new NavCallback() {
                   @Override
                    public void onArrival(Postcard postcard) {
                     }
                     @Override
                     public void onInterrupt(Postcard postcard) {
                           Log.d("ARouter", "被拦截了");
                      }
                 });

5.5申明拦截器(拦截跳转过程,面向切面编程)

// 比较经典的应用就是在跳转过程中处理登陆事件,这样就不需要在目标页重复做登陆检查
// 拦截器会在跳转之间执行,多个拦截器会按优先级顺序依次执行
@Interceptor(priority = 8, name = "测试用拦截器")
public class TestInterceptor implements IInterceptor {
    @Override
    public void process(Postcard postcard, InterceptorCallback callback) {
    ...
    callback.onContinue(postcard);  // 处理完成,交还控制权
    // callback.onInterrupt(new RuntimeException("我觉得有点异常"));      // 觉得有问题,中断路由流程
    // 以上两种至少需要调用其中一种,否则不会继续路由
    }
    @Override
    public void init(Context context) {
    // 拦截器的初始化,会在sdk初始化的时候调用该方法,仅会调用一次
    }
}

5.6 为目标页面声明更多信息

// 我们经常需要在目标页面中配置一些属性,比方说"是否需要登陆"之类的
// 可以通过 Route 注解中的 extras 属性进行扩展,这个属性是一个 int值,换句话说,单个int有4字节,也就是32位,可以配置32个开关
// 剩下的可以自行发挥,通过字节操作可以标识32个开关,通过开关标记目标页面的一些属性,在拦截器中可以拿到这个标记进行业务逻辑判断
@Route(path = "/test/activity", extras = Consts.XXXX)

5.7依赖注入解耦
注册需要依赖注入的对象

@Route(path = "/provider/testP")
public class TestProvider implements IProvider {
    @Override
    public void init(Context context) {
    }
    public String test(){
       return ("Hello Provider!");
    }
}

获取对象 & 使用

ARouter.getInstance().navigation(TestProvider.class).test();

ARouter 的GitHub:https://github.com/alibaba/AR...有很多路由的使用
三:路由ARouter结构解析
image.png
image.png
ARouter主要由三部分组成,包括对外提供的api调用模块、注解模块以及编译时通过注解生产相关的类模块。

  • arouter-annotation注解的声明和信息存储类的模块
  • arouter-compiler编译期解析注解信息并生成相应类以便进行注入的模块
  • arouter-api核心调用Api功能的模块

annotation模块
Route(path)、Interceptor(拦截)、Autowired(数据获取)都是在开发是需要的注解
compiler模块,这是编译产生的文件
AutoWiredProcessor(自动装配处理器)、InterceptorProcessor(拦截器处理器)、RouteProcessor(路由路径处理器)分别为annotation模块对应的Autowired、Interceptor、Route在项目编译时产生相关的类文件。
api模块
主要是ARouter具体实现和对外暴露使用的api
image.png

结尾:知识学习,由大到小


Rocky_ruan
57 声望5 粉丝

不积跬步,无以至千里