ARouter源码解析05-自动参数注入

这篇文章来分析ARouter的自动参数注入

以ARouter示例程序中的BlankFragment为例

@Route(path = "/test/fragment")
public class BlankFragment extends Fragment {

    @Autowired
    String name;

    @Autowired(required = true)
    TestObj obj;

    public BlankFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        TextView textView = new TextView(getActivity());
        return textView;
    }
}  

在编译的时候,会在app/build/generated/source/apt/debug/com.alibaba.android.arouter/生成BlankFragment$$ARouter$$Autowired

public class BlankFragment$$ARouter$$Autowired implements ISyringe {
  private SerializationService serializationService;

  @Override
  public void inject(Object target) {
    serializationService = ARouter.getInstance().navigation(SerializationService.class);;
    BlankFragment substitute = (BlankFragment)target;
    substitute.name = substitute.getArguments().getString("name");
    if (null != serializationService) {
      substitute.obj = serializationService.json2Object(substitute.getArguments().getString("obj"), TestObj.class);
    }
  }
}  

即,调用inject(),就会将参数进行赋值。
那么,什么时候调用的inject()呢?

在 InstrumentationHook这个类中,会去判断是否是可以自动inject的,如果autdoInject标记为true,则会通过反射来调用相关Autowired的inject()方法。但是,在这个类已经被标记为Deprecated,注释提示我们现在使用ARouter.getInstance().inject(this),同时查看官方文档,也是需要手动使用inject()来进行参数注入。

/**
 * Use ARouter.getInstance().inject(this) now!
 *
 * Hook the instrumentation, inject values for activity's field.
 * Support normal activity only, not contain unit test.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 2016/11/24 16:42
 */
@Deprecated
public class InstrumentationHook extends Instrumentation {
    /**
     * Hook the instrumentation's newActivity, inject
     * <p>
     * Perform instantiation of the process's {@link Activity} object.  The
     * default implementation provides the normal system behavior.
     *
     * @param cl        The ClassLoader with which to instantiate the object.
     * @param className The name of the class implementing the Activity
     *                  object.
     * @param intent    The Intent object that specified the activity class being
     *                  instantiated.
     * @return The newly instantiated Activity object.
     */
    public Activity newActivity(ClassLoader cl, String className,
                                Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {

//        return (Activity)cl.loadClass(className).newInstance();

        Class<?> targetActivity = cl.loadClass(className);
        Object instanceOfTarget = targetActivity.newInstance();

        if (ARouter.canAutoInject()) {
            String[] autoInjectParams = intent.getStringArrayExtra(ARouter.AUTO_INJECT);
            if (null != autoInjectParams && autoInjectParams.length > 0) {
                for (String paramsName : autoInjectParams) {
                    Object value = intent.getExtras().get(TextUtils.getLeft(paramsName));
                    if (null != value) {
                        try {
                            Field injectField = targetActivity.getDeclaredField(TextUtils.getLeft(paramsName));
                            injectField.setAccessible(true);
                            injectField.set(instanceOfTarget, value);
                        } catch (Exception e) {
                            ARouter.logger.error(Consts.TAG, "Inject values for activity error! [" + e.getMessage() + "]");
                        }
                    }
                }
            }
        }

        return (Activity) instanceOfTarget;
    }
}  

没错,现在的ARouter的自动参数注入需要手动调用ARouter.getInstance().inject()。

再来看ARouter.getInstance().inject(),最终会调用AutowiredServiceImpl的autowire方法

@Route(path = "/arouter/service/autowired")
public class AutowiredServiceImpl implements AutowiredService {
    private LruCache<String, ISyringe> classCache;
    private List<String> blackList;

    @Override
    public void init(Context context) {
        classCache = new LruCache<>(66);
        blackList = new ArrayList<>();
    }

    @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.
        }
    }
}  

可以看到,autowire()中,会通过反射,调用我们上面提到的IDE自动生成的BlankFragment$$ARouter$$Autowired这个类的inject()
然后在inject()中,再进行赋值,这样就完成了自动注入的过程。

至此,我们分析完了ARouter的自动参数注入。

HkeW3mModifier2.05 这是一个修改MPQ格式文件的工具 可以修改加密过的MPQ文件 还带有强大的资源搜索功能 可以搜索出魔兽地图中大部分资源 重建列表 解压模型能智能解压相关贴图 ----------------------------------------------- 1.如果不稳定出现错误重启本软件即可 2.修改文件不必分析列表 只要在文件选择那边填入正确名称就行 (软件会自动分析J文件的位置 修改脚本的话直接改就行了) 3.无视目前已知的MPQ头加密 可以直接修改 4.如果重压缩卡死 生成超大文件可以试试修复文件头 ----------------------------------------------- 2.05版更新 平安夜特别版 [+]脚本注入功能 可以轻松往地图里注入任何脚本 默认是hke1.25B喜欢可以自己改 HkeData\下的g.j f.j m.j分别代表脚本的3部分 自己改就是了 脚本进游戏乱码的话你可以用窗口上的工具转一下UTF-8编码 真的很累了 以后会不会更新很难说了 给大家留个纪念吧 2.04版更新 [+]加入图片预览功能 可以轻松查看资源 你可以直接打开预览窗口点击文件列表中的图片 或者把外部图片直接拖进预览窗 当也可以直接打开 支持大部分常见图片格式 支持图片转化 不过这个功能还是有点小问题 没办法飞雪大人的那个库太大了 我换了个方法 但是转BLP有经常会失败 [+]未打开地图是支持拖放进窗口打开了(关闭后可以再次拖放打开) 注意:已经打开的地图拖放会添加文件 [-]压缩设置窗体整合到选项设置中 2.03版更新 [+]加入了小提示功能 充分利用状态栏 [+]加入保存设置功能 设置可以保存了 [-]缩小窗口体积 解决低分辨率显示不全问题 [-]减小了程序体积 2.02版更新 [+]加入了文件重命名功能 [+]分析文件是显示非空Hash的数目 [-]优化了内存管理 2.01版更新 [-]紧急修正不能解压的bug 2.00版更新 [+]解压模型是自动解压相关贴图的选项 [+]加入了对战役文件的支持 (还顺便能分析没list的 不过为了速度只分析外部资源 效果还是比darkfall大人的好哦) [+]加入了压缩类型设置 防止类型不对的压缩破坏文件 compress.hke不要弄丢了哦 是配置文件 [-]修正个bug 1.93版更新 [+]加上了个大大的修复按钮 眼神不好的朋友应该也能看见了 如果重压缩卡死可以试试他(当然要在压缩前啦) 还原未必好啦 没必要的话最好还是不用还原 [-]修正了个可能内存泄露的问题 1.92版更新 [+]新增关闭时删除临时文件 [-]修正热键冲突 [-]修正个bug 1.91版更新 [-]一些文件分析不出来的问题和一个显示错误 1.9版更新 [+]新增了添加方式 可以比较方便的添加文件 [+]新增拖放添加 打开地图可以直接吧文件拖到程序上添加 由于技术不够 本来想写拖放解压的看样子不行了 1.8版更新 [+]新增双击列表运行文件的功能 [+]新增解压列表文件功能 [+]新增筛选结果功能 可以保留匹配项 也可以去除匹配项 嘿嘿 还算方便吧 [-]修正了查找算法 能搜到更多资源 1.7版更新 [+]加上了保存列表和列表上的右键菜单 [-]修正了算法 智能分析基本上能找到魔兽地图所有资源文件 [-]去掉了自动重压缩的默认项 优化速度 [-]修正2处bug 1.6版更新 [+]加入智能分析文件列表功能 虽然和白银大人的还有一定差距 大部分文件还是行滴 我有空会完善的 [-]修正3个小bug 1.5版更新 [+]加入了分析文件列表的功能 这个暂时只是用listfile获取 智能分析下次再说吧 listfile.txt可以自己更新啦 但不要删掉 不然找到的可能少 [+]加入了添加文件名称不同时候提示的功能 防止覆盖文件 1.4版更新 [-]修正个小问题现在可以完全无视目前任何加密直接改了 不用还原文件头啦 当然你还原也行不过有点图会还原坏掉 1.3版更新 [-]修正了个可能是逻辑的问题 [+]加入了只读打开功能 勾起来可以只读打开不修改文件 [+]加入了个设置语言的功能 嘿嘿纯属无聊 不过说不定有用 1.2版更新 [+]加入MPQ头修复功能 没办法有的图不修复会卡死 不喜欢的话可以把那个选项勾掉 1.1版更新 [+]加入了读取/修改地图显示名的功能 [-]修正了个逻辑问题 [-]修正了部分兼容性问题 优化速度 一个无视已知大部分MPQ加密的编辑器 不用还原文件头即可使用 读取方面采用Storm保存和魔兽一致 如果读不出魔兽也不能读滴 可以不还原文件头编辑文件 嘿嘿强大吧 添加的时候注意加进去的文件是你填的自定义文件 和本身文件名无关 比如你写war3map.j 然后添加一个图片 那个图片会覆盖war3map.j
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

氦客

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值