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