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

来源:互联网 发布:搜歌词的软件 编辑:程序博客网 时间:2024/06/03 03:12

这篇文章来分析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 */@Deprecatedpublic 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的自动参数注入。

原创粉丝点击