arouter 自定生成autowired

2023-11-17

原文地址

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

arouter 自定生成autowired 的相关文章

  • 如何在 HandlerInterceptorAdapter 中添加 HttpServletRequest 标头?

    我正在尝试将授权标头添加到我的请求中 作为我们切换环境时的临时解决方法 我试图在扩展 HandlerInterceptorAdapter 的拦截器中处理它 我使用 MutableHttpServletRequest 类制作here http
  • cordova插件条码扫描仪打不开扫描

    我的条形码扫描仪插件有问题 我不是天才 我不太了解如何编写网络应用程序 我使用phonegap和cordova 并且尝试制作一个网络应用程序 在单击链接后扫描条形码 我之前已经使用此命令行安装了该插件 cordova plugin add
  • 确定序列化对象的类型

    我需要通过套接字发送消息 从用户到引擎的请求 以及从引擎到用户的响应 所以流程本质上是 serialized request Server lt network gt Client serialized response request r
  • java setFullScreenWindow 在 Mac 中隐藏登录对话框

    我使用的是全屏窗口 类似于屏幕保护程序 使用这里的方法 GraphicsEnvironment getLocalGraphicsEnvironment getDefaultScreenDevice setFullScreenWindow t
  • 具有 JPA 持久性的 Spring 状态机 - 存储库使用

    我试图弄清楚如何轻松使用 Spring 状态机 包括使用 JPA 进行持久化 这是我正在处理的问题 不兼容的数据类型 工厂和持久性 在程序的某个时刻 我想使用连接到用户的状态机 有用于此目的的存储库 项目spring statemachin
  • Android 发布到 facebook 墙,stream.publish 几天来就中断了

    我有很多使用 FB android sdk 发布的应用程序 github com facebook facebook android sdk 我所有使用 FB 的应用程序几天后就停止工作了 这必然是 FB 方面的更改或错误 因为我的应用程序
  • 纱线上的火花,连接到资源管理器 /0.0.0.0:8032

    我正在我的开发机器 Mac 上编写 Spark 程序 hadoop的版本是2 6 spark的版本是1 6 2 hadoop集群有3个节点 当然都在linux机器上 我在idea IDE中以spark独立模式运行spark程序 它运行成功
  • 在尝试使用 GPS 之前如何检查 GPS 是否已启用

    我有以下代码 但效果不好 因为有时 GPS 需要很长时间 我该如何执行以下操作 检查GPS是否启用 如果启用了 GPS 请使用 GPS 否则请使用网络提供商 如果 GPS 时间超过 30 秒 请使用网络 我可以使用时间或 Thread sl
  • 使用 Glide 库设置图像加载完成后进度条的可见性

    您好 我想要一个图像进度条 该进度条将在图像加载时显示 但当图像加载完成时 我想将其设置为消失 早些时候我为此使用了毕加索库 但我不知道如何将它与 Glide 库一起使用 我知道有一些资源就绪功能 但我不知道如何使用它 谁能帮我 毕加索图书
  • 用于层次结构树角色的 Spring Security / Java EE 解决方案

    我知道 Spring Security 非常适合标准角色和基于权限的授权 我不确定的是这种情况 系统中管理着 10 000 名员工 员工被组织成组织结构图 跨部门的谁向谁报告的树 其中一些员工是用户 这些用户仅被允许访问其职责范围内的员工
  • 确定视图是否在屏幕上 - Android

    我对这个有点困惑 首先也是最重要的是 以下链接很有用 但是我提出了一些可见性问题 链接 检查视图可见性 https stackoverflow com questions 4628800 android how to check if a
  • 如何在不反编译的情况下更改已编译的.class文件?

    我想更改 class 文件方法 我安装 JD Eclipse Decompiler 并打开 class 文件 我添加了一些代码并保存 class 文件 但是 class 文件没有改变 我不知道如何使用反编译器 如果可能的话 如何在不使用反编
  • HTTP 状态 405 - 此 URL java servlet 不支持 HTTP 方法 POST [重复]

    这个问题在这里已经有答案了 我无法使页面正常工作 我有要发布的表单方法和我的 servlet 实现doPost 然而 它不断地向我表明我并不支持POST方法 我只是想做一个简单的网站并将值插入到我的 MySQL 数据库中 type Stat
  • 获取当前图片在图库中显示的位置

    在我的应用程序中 我有一个图片库 但我想检测当前显示图像的位置 例如 当我启动我的活动时 位置是 0 但是当我在图库中滚动时 我想获取当前显示图像的位置 我尝试过 OnFocusChanged OnItemClicked 但只有当我单击图库
  • 如何以编程方式创建 CardView

    我正在开发一个 Android 应用程序Java Android Studio 我想在活动中创建CardView以编程方式 我想将以下属性设置为CardView layout width wrap content layout row 0
  • 如何制作一个makefile只用于编译一些java文件?

    我有三个java文件 名为A java B java C java A将创建对象B B将创建对象C 但我以前从未构建过makefile 有谁可以帮我构建一个 makefile 来编译这三个 java 文件吗 我应该使用什么工具来制作 mak
  • 如何使用自定义 JDK 构建 Jenkins 项目?

    我有一个常规的 Jenkins 实例 运行一些多分支管道 该实例在 JDK 11 上运行 因为 Jenkins 并不真正支持更高版本 没关系 但不好的是 我的所有管道似乎也都受到 Java 11 的限制 Jenkins 仅使用它自己也使用的
  • 画布:尝试使用回收的位图错误

    我是一个相当新的程序员 所以任何建议将不胜感激 我有一个类 每次调用它时都会在循环中运行 AsyncTask AsyncTask 看起来像这样 public class LoadImageTask extends AsyncTask
  • 如何建立与 FileZilla Server 1.2.0 的 FTPS 数据连接

    使用 Apache commons net 的 Java FTPSClient 进行会话恢复是一个已知问题 会话恢复是 FTPS 服务器数据连接所需的一项安全功能 Apache FTPSClient 不支持会话恢复 并且 JDK API 使
  • java中void的作用是什么?

    返回类型 方法返回值的数据类型 如果方法不返回值 则返回 void http download oracle com javase tutorial java javaOO methods html http download oracle

随机推荐