Android之ARouter使用和原理解析

ARouter使用和原理解析

github:https://github.com/alibaba/ARouter

一:ARouter介绍

组件化逐渐成为热潮,组件化可以使业务逻辑高度解耦、模块分离,提高开发效率,更有利于多人协作并行开发。组件化中两个单向依赖的module之间互相启动对方的Activity,因为没有相互引用startActivity()是实现不了的,必须需要一个协定的通信方式,此时ARouter路由框架就派上用场了。ARouter是阿里巴巴开源路由框架,主要解决组件间、模块间的界面跳转问题。

 

二:ARouter基础功能使用

1):添加依赖和配置

java和kotlin配置不一样,本文以kotlin和gradle3.4+进行配置的。

在module中build.gradle配置

apply plugin: 'kotlin-kapt'

kapt {
    arguments {
        arg("AROUTER_MODULE_NAME", project.getName())
    }
}

dependencies {
    implementation 'com.alibaba:arouter-api:1.5.0'
    kapt 'com.alibaba:arouter-compiler:1.2.2'
}

2)::在目标页面Activity添加注解

// 在支持路由的页面上添加注解(必选) // 这里的路径需要注意的是至少需要有两级,/xx/xx

@Route(path = "/test/activity")
public class YourActivity extend Activity { ... }

3):初始化SDK

  /**
     * 初始化ARouter
     */
    private fun initARouter() {
        if (BuildConfig.DEBUG) { //如果在debug模式下
            // 打印日志,默认关闭
            ARouter.openLog()
            // 开启调试模式,默认关闭(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
            ARouter.openDebug()
            // 打印日志的时候打印线程堆栈
            ARouter.printStackTrace()
        }
        // 尽可能早,推荐在Application中初始化
        ARouter.init(this)
    }

 

4.发起路由操作

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

三:ARouter原理

1):@Route注解的作用

在需要对其他module提供调用的Activity中,都需要声明@Route注解,我们称之为路由地址。

@Route(path = "/userCenter/login")

class LoginActivity : AppCompatActivity(){...}

那么这个注解有什么用呢?

路由框架会在项目的编译期通过注解处理器扫描所有@Route注解的Activity类,然后将Route注解中的path地址和Activity.class文件的映射关系保存到它自己生成的java文件的map中。

路径:build/generated/source/kapt/debug/com/alibaba/android/arouter

伪代码:

public class ARouter$$Root$$app implements IRouteRoot {
  @Override
  public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) {
    routes.put("account", ARouter$$Group$$account.class);
    routes.put("shop", ARouter$$Group$$shop.class);
  }
}

public class ARouter$$Group$$account implements IRouteGroup {
  @Override
  public void loadInto(Map<String, RouteMeta> atlas) {
    atlas.put("/account/order", RouteMeta.build(RouteType.ACTIVITY, RegionSelectActivity.class, "/account/order", "account", null, -1, -2147483648));
  }
}

2):ARouter如何实现跳转

    //用ARouter启动Activity,代码如下:

            ARouter.getInstance().build("/userCenter/login").navigation();

    //实现伪代码:
    public void login(String name, String password) {

        HashMap<String, ClassBean> route = MyRouters.getRouteInfo(new HashMap<String, ClassBean>);

        LoginActivity.class classBean = route.get("/userCenter/login");

        Intent intent = new Intent(this, classBean);

        intent.putExtra("name", name);

        intent.putExtra("password", password);

        startActivity(intent);
}

 

总结:

1、我们通过@Route,将path和目标类进行关联。

2、在编译阶段,注解处理器RouteProcessor会在com.alibaba.android.arouter.routes包下以固定的拼接规则生成ARouter$$Root$$app和多个ARouter$$Group$$xxx文件。以map的形式,在group文件中存储对应的path和目标类信息,在root文件中存储groupName和对应的group类的class对象。

3、在application中调用init进行初始化。

4、在init方法中,先调用loadRouterMap方法。这是一个空实现,是给插件插桩用的。我们可以配置Gradle插件实现路由表的自动加载,代替扫描dex文件的方式加载路由表。缩短初始化时间和解决应用加固无法直接访问dex文件的问题。

arouter-auto-register插件将在此方法内部生成代码,调用此方法以注册所有路由器,拦截器和提供程序。在这里会对registerByPlugin置为true。这样就避免扫描dex文件。

5、如果没有配置gradel插件实现路由表的自动加载,我们就需要自己扫描dex文件。

6、获取全局路由信息是一个比较耗时的操作,所以 ARouter 就通过将全局路由信息缓存到 SP 中来实现复用。

7、如果当前开启了 debug 模式或者通过本地 SP 缓存判断出 app 的版本前后发生了变化,那么就重新获取全局路由信息,否则就还是使用之前缓存到 SP 中的数据。

8、通过dex扫描com.alibaba.android.arouter.routes包下的文件,然后将文件的全路径存储到HashSet中,然后存到sp中。也就是说sp存储了在 com.alibaba.android.arouter.routes 这个包下自动生成的辅助文件的全路径。

9、通过判断路径名的前缀字符串,就可以知道该类文件对应什么类型,然后通过反射构建不同类型的对象,通过调用对象的loadInto方法将路由信息存到 Warehouse 的 Map 中。

10、对于大型App来说,一次性加载路由信息到内存,会占据大量内存。所以是按需加载。

11、假如说有/account/userHome,首先通过反射创建root类,调用loadInto方法将键值对保存到groupIndex的HashMap中。

12、当后续跳转到group为account的页面时,再通过反射调用account类的loadInto方法,将键值对存到routes的HashMap中。实现了按需加载

 

四:ARouter进阶用法

1):跳转界面不带参

2):跳转界面带参

3):跳转界面传递对象

4):Uri跳转

5):跳转结果监听

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

7):为目标页面声明更多信息

8):依赖注入解耦

五、ARouter实现参数注入

  • 控制反转:通过接口获得实现类。以一定的拼接规则,通过反射的反射获得实现类。
  • 通过setIntent进行赋值
  • 注解处理器会在编译阶段扫描有被Autowired注解标注的变量,根据这个类和变量的情况生成一份Java类Autowired。这个类实现了IProvider接口,实现inject方法,在inject方法中 通过getIntent获取值,然后对注解变量进行赋值。这里用到了控制反转,通过接口IProvider获得实现类。
  • 我们在onCreate调用ARouter.getInstance().inject(this)方法,在inject中通过一定的拼接规则获取到上文所述的Java类ARouter$$Autowired的className,通过反射创建类对象。后调用对象的injecct方法,完成对数据的赋值。
ISyringe autowiredHelper = (ISyringe) Class.forName(instance.getClass().getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance();
autowiredHelper.inject(instance);

补充:

Q1:组件化中模块之间的Activity跳转,为什么选择ARouter路由跳转

1):隐式跳转,但是一个项目中不可能所有的跳转都是隐式的,这样Manifest文件会有很多过滤配置,而且非常不利于后期维护。

2):反射拿到Activity的class文件也可以实现跳转,

缺点:1大量的使用反射跳转对性能会有影响,

2.需要拿到Activity的类文件,在组件开发的时候,想拿到其他module的类文件是很麻烦的,因为组件开发的时候组件module之间是没有相互引用的,你只能通过找到类的路径去反射拿到这个class。

 

Q2:什么是APT

APT是Annotation Processing Tool的简称,即注解处理工具。apt是在编译期对代码中指定的注解进行解析,然后做一些其他处理(如通过javapoet生成新的Java文件)。我们常用的ButterKnife,其原理就是通过注解处理器在编译期扫描代码中加入的@BindView、@OnClick等注解进行扫描处理,然后生成XXX_ViewBinding类,实现了view的绑定。

 

 

 

 
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android ARouter 是一个用于实现组件化、模块化开发的路由框架,它提供了一种简单的方式来实现不同组件之间的跳转和通信。 使用 ARouter 的步骤如下: 1. 在项目的 build.gradle 文件中添加依赖: ```groovy implementation 'com.alibaba:arouter-api:x.x.x' annotationProcessor 'com.alibaba:arouter-compiler:x.x.x' ``` 请将 `x.x.x` 替换为最新的版本号。 2. 在需要使用 ARouter 的模块中,创建一个类似于 Application 的类,并在其 `onCreate()` 方法中进行 ARouter 的初始化: ```java public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); if (BuildConfig.DEBUG) { ARouter.openLog(); ARouter.openDebug(); } ARouter.init(this); } } ``` 3. 在需要跳转到的目标页面中,使用 `@Route` 注解进行标记,以便 ARouter 进行识别: ```java @Route(path = "/path/to/target") public class TargetActivity extends AppCompatActivity { // ... } ``` 4. 在需要跳转的地方,通过调用 `ARouter.getInstance().build("/path/to/target").navigation()` 来实现页面跳转: ```java ARouter.getInstance().build("/path/to/target").navigation(); ``` 5. 如果需要传递参数,可以使用 `withXxx` 方法来添加参数: ```java ARouter.getInstance() .build("/path/to/target") .withString("key", "value") .navigation(); ``` 通过以上步骤,你就可以在 Android 项目中使用 ARouter 进行页面跳转和参数传递了。当然,ARouter 还提供了其他功能,比如拦截器、URI 跳转等,你可以根据具体需求进行使用。希望对你有所帮助!如果还有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值