arouter 自定生成autowired

原文地址

Evil Mouth’s Blog
ARouter @Autowired 自动注入
May 31, 2020

前言
ARouter 有一个@Autowired 的注解,能自动帮我们赋值一些变量,例如

public class MainFragment {
@Autowired
String name;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Arouter.getInstance().inject(this);

    System.out.println(name);
}

}
通过Arouter.getInstance().inject(this);就能将 Activity 传输的一些值自动帮我们赋值上对应变量,省去我们手动去调用getIntent().getString(xxx)

inject(this)
那么看下它做了什么,翻了几下发现,ARouter 会做以下几步操作 1、APT 编译期间扫描@Autowired 字段的文件并生成 MainFragment A R o u t e r ARouter ARouterAutowired 文件

A R o u t e r ARouter ARouterAutowired 类实现了 ISyringe 接口,拥有一个 inject(Object)的方法,这里面就是赋值的代码
public class MainFragment A R o u t e r ARouter ARouterAutowired implements ISyringe {
private SerializationService serializationService;

@Override
public void inject(Object target) {
MainFragment substitute = (MainFragment)target;
substitute.name = substitute.getArguments().getString(“name”);
substitute.age = substitute.getArguments().getInt(“age”);
}
}
2、Arouter.getInstance().inject(this);则是通过反射创建了 A R o u t e r ARouter ARouterAutowired 类并调用 inject 方法实现自动赋值

@Override
public void autowire(Object instance) {
String className = instance.getClass().getName();
try {
if (!blackList.contains(className)) {
ISyringe autowiredHelper = classCache.get(className);
if (null == autowiredHelper) { // No cache.
autowiredHelper = (ISyringe) Class.forName(instance.getClass().getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance();
}
autowiredHelper.inject(instance);
classCache.put(className, autowiredHelper);
}
} catch (Exception ex) {
blackList.add(className); // This instance need not autowired.
}
}
思考
众所周知反射的性能是差的,那么有什么办法不反射吗,答案是有的,那就是直接 new MainFragment A R o u t e r ARouter ARouterAutowired().inject(this);

然而在代码没编译之前,MainFragment A R o u t e r ARouter ARouterAutowired 这个类是还没生成的,自然无法直接调用。况且这样还有个问题,那就是每个 Activity 或 Fragment 生成的类都是唯一的,我们也不可能在每个地方手动 new+inject,这样还不如反射来的方便

这时候就需要 Android 提供的工具 Transform 了

Transform 开发
核心原理
利用 Transform,在编译期间往使用了@Autowired 的 Activity 或 Fragment 类的 onCreate(Bundle)方法自动注入new xxx A R o u t e r ARouter ARouterAutowired().inject(this);这行代码

过程
1、扫描整个项目里名称后缀为 A R o u t e r ARouter ARouterAutowired 的 class 文件 2、以此找到对应的 Activity 或 Fragment 文件 3、利用 ASM 库对该文件进行访问 4、访问到 onCreate(Bundle)方法时,在 super.onCreate 前写入 inject 方法

结果
编译完成后,可以通过 apk 包分析或这在 app\build\intermediates\transforms 目录下找到 MainFragment 文件编译后的代码,可以看见 MainFragment 的 onCreate 方法里面多了一行代码,就是上面所想要的 new MainFragment A R o u t e r ARouter ARouterAutowired().inject(this);

再次思考
虽然利用 Transform 可以解决反射的问题,但无疑也带来了一个问题,就是项目协作上,其他人不了解的话会很奇怪。我的做法是在 A R o u t e r ARouter ARouterAutowired 类加了行注释,起码别人在看这个类的时候能知道什么时候会 inject。 至于怎么加这行注释,就靠各位发挥了

本项目例子已开源Github

— Evil Mouth

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值