目录
一、ARouter功能和原生功能对比
二、页面的注册和调用
三、页面启动的实现
四、页面启动总结
五、依赖注入的使用
六、依赖注入的实现
七、依赖注入总结
一、ARouter功能和原生功能对比
原生功能
1、页面跳转,原生分为显示和隐式跳转,显示跳转耦合度太高,隐式跳转难于管理,不好协作
2,原生页面跳转startActivity之后就无法插手任何操作,导致跳转失败无法降级
ARouter功能
1、路由管理(通过url解决依赖问题,通过分布式页面管理path解决隐式启动管理问题)
2、在页面跳转时可实现拦截功能,如果页面跳转失败可实现兜底功能(通过AOP解决跳转过程无法控问题制和页面降级问题)
3、统一native和h5跳转问题
4、项目组件化开发解耦,减少依赖
5、依赖注入实现成员变量的自动赋值
6、支持java,kotlin注解解析
二、源码剖析
1、项目目录
arouter-annotation ARouter的注解定义
arouter-api 对外界提供api面向的是运行时
arouter-compiler 对应的是编译期,依据规则自动生成中间类。他提供了RouteProcessor用于路由注解解析,InterceptorProcessor用于拦截器注解解析,AutowiredProcessor用于依赖注入注解解析
arouter-gradle-plugin 是一个插件在编译期找到LogisticsCenter的loadRouterMap()方法,将编译时期生成的类和方法注册到LogisticsCenter中,实现自动注册页面和依赖注入功能
2、页面注册和调用
2.1 在Application中初始化sdk
ARouter.init(mApplication);
2.2 注册一个页面
@Route(path = /main/about)
class AboutActivity : BaseActivity(){}
2.3 ARouter自动生成类
会通过compiler的RouteProcessor生成一个继承自IRouteGroup的类
public class ARouter$$Group$$main implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put("/main/about", RouteMeta.build(RouteType.ACTIVITY, AboutActivity.class, "/main/about", "main", null, -1, -2147483648));
}
}
2.4 启动页面
ARouter.getInstance().build(/main/about).navigation()
3 页面启动源码解析
3.1 标记页面
使用@Route注解并且添加path参数path必须是/group/xx,因为加载的时候是以group为组加载的
3.2 解析页面
通过RouteProcessor在编译时期解析@Route注解标记的页面生成继承自IRouteGroup的ARouter$$Group$$main类,
3.3 将生成的类注入到ARouter中
这个技术使用的是自定义一个gradle插件,Google提供一个Transform的类用于在给已经生成的class类增加功能,ARouter使用的RegisterTransform遍历所有生成的class文件找到LogisticsCenter类,然后在LogisticsCenter中loadRouterMap()方法编入registerRouteRoot(new IRouteGroup的ARouter$$Group$$main())代码,registerRouteRoot()方法代码如下:
/**
* method for arouter-auto-register plugin to register Routers
* @param routeRoot IRouteRoot implementation class in the package: com.alibaba.android.arouter.core.routers
* @author billy.qi <a href="mailto:qiyilike@163.com">Contact me.</a>
* @since 2017-12-06
*/
private static void registerRouteRoot(IRouteRoot routeRoot) {
markRegisteredByPlugin();
if (routeRoot != null) {
routeRoot.loadInto(Warehouse.groupsIndex);
}
}
注意 routeRoot.loadInto(Warehouse.groupsIndex);这个调用的IRouteRoot的loadInto(),也就是ARouter为我们生成的ARouter$$Group$$main类的loadInfo(),代码如下:
public class ARouter$$Group$$main implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put("/main/about", RouteMeta.build(RouteType.ACTIVITY, AboutActivity.class, "/main/about", "main", null, -1, -2147483648));
}
}
这样就会把ARouter为我们生成的类注入到Warehouse.groupsIndex这个Map中,这样就实现了将生成类注入到ARouter中,准备工作完成,剩余工作就是ARouter启动页面了
3.4 启动页面
启动页面我们可以调用一下两种方法,不包含Context的使用的是Application的Context,intent标记设置的是intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ARouter.getInstance().build(/main/about).navigation();
ARouter.getInstance().build(/main/about).navigation(activity);
------------- ARouter.getInstance().build(/main/about) start -------------
ARouter.getInstance().build(/main/about)源码
ARouter.java
/**
* Build the roadmap, draw a postcard.
*
* @param path Where you go.
*/
public Postcard build(String path) {
return _ARouter.getInstance().build(path);
}
_ARouter.getInstance().build(path);源码
_ARouter.java
/**
* Build postcard by path and default group
*/
protected Postcard build(String path) {
if (TextUtils.isEmpty(path)) {
throw new HandlerException(Consts.TAG + "Parameter is invalid!");
} else {
PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);//①
if (null != pService) {
path = pService.forString(path);
}
return build(path, extractGroup(path));
}
}
这里要重点关注PathReplaceService,在开始所有页面之前通过这个类实现一个PostCard,复写这个接口可以实现对所路由的拦截,并修改路由,拦截代码如下:
PathReplaceServiceImpl.java
@Route(path = "/path/replace")
class PathReplaceServiceImpl :PathReplaceService{
override fun forString(path: String?): String {
Log.d("yyy","path = ${path}")
return path ?:""
}
override fun forUri(uri: Uri?): Uri? {
Log.d("yyy","uri = ${uri.toString()}")
return uri
}
override fun init(context: Context?) {
Log.d("yyy","content")
}
}
那么PathReplaceService是如何实现URL预处理的呢,ARouter.getInstance().navigation(PathReplaceService.class);最后会调用到_ARouter.getInstance().navigation(service);这个方法的源码如下:
_ARouter.java
protected <T> T navigation(Class<? extends T> service) {
try {
Postcard postcard = LogisticsCenter.buildProvider(service.getName());//①
// Compatible 1.0.5 compiler sdk.
// Earlier versions did not use the fully qualified name to get the service
if (null == postcard) {
// No service, or this service in old version.
postcard = LogisticsCenter.buildProvider(service.getSimpleName());//②
}
if (null == postcard) {
return null;
}
LogisticsCenter.completion(postcard);//③
return (T) postcard.getProvider();//④
} catch (NoRouteFoundException ex) {
logger.warning(Consts.TAG, ex.getMessage());
return null;
}
}
LogisticsCenter.buildProvider(service.getName());源码如下:
LogisticsCenter.java
/**
* Build postcard by serviceName
*
* @param serviceName interfaceName
* @return postcard
*/
public static Postcard buildProvider(String serviceName) {
RouteMeta meta = Warehouse.providersIndex.get(serviceName);
if (null == meta) {
return null;
} else {
return new Postcard(meta.getPath(), meta.getGroup());
}
}
从LogisticsCenter中通过service的name(这个name就是PathReplaceService)取出我们自定义的PathReplaceServiceImpl,他被解析存储在Warehouse.providersIndex中。然后在创建一个Postcard实例返回到_ARouter.getInstance().navigation(service)方法中,继续向下执行到LogisticsCenter.completion(postcard);这个方法源码如下:
/**
* Completion the postcard by route metas
*
* @param postcard Incomplete postcard, should complete by this method.
*/
public synchronized static void completion(Postcard postcard) {
if (null == postcard) {
throw new NoRouteFoundException(TAG + "No postcard!");
}
RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
if (null == routeMeta) { // Maybe its does't exist, or didn't load.
//这里进行错误检测
Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup()); // Load route meta.
if (null == groupMeta) {
throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");
} else {
···
//开始以group为单位加载数据到内存
IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();
iGroupInstance.loadInto(Warehouse.routes);
Warehouse.groupsIndex.remove(postcard.getGroup());
····
//重新装载
completion(postcard); // Reload
}
} else {
//为postcard添加类型
postcard.setDestination(routeMeta.getDestination());
postcard.setType(routeMeta.getType());
postcard.setPriority(routeMeta.getPriority());
postcard.setExtra(routeMeta.getExtra());
Uri rawUri = postcard.getUri();
if (null != rawUri) { // Try to set params into bundle.
Map<String, String> resultMap = TextUtils.splitQueryParameters(rawUri);
Map<String, Integer> paramsType = routeMeta.getParamsType();
if (MapUtils.isNotEmpty(paramsType)) {
// Set value by its type, just for params which annotation by @Param
for (Map.Entry<String, Integer> params : paramsType.entrySet()) {
setValue(postcard,
params.getValue(),
params.getKey(),
resultMap.get(params.getKey()));
}
// Save params name which need auto inject.
postcard.getExtras().putStringArray(ARouter.AUTO_INJECT, paramsType.keySet().toArray(new String[]{}));
}
// Save raw uri
postcard.withString(ARouter.RAW_URI, rawUri.toString());
}
switch (routeMeta.getType()) {
case PROVIDER: // if the route is provider, should find its instance
// Its provider, so it must implement IProvider
Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
IProvider instance = Warehouse.providers.get(providerMeta);
if (null == instance) { // There's no instance of this provider
IProvider provider;
····
//这里调用IProvider的init(),并且装载Provider到内存中
provider = providerMeta.getConstructor().newInstance();
provider.init(mContext);
Warehouse.providers.put(providerMeta, provider);
instance = provider;
···
}
postcard.setProvider(instance);
//如果开启绿色通道直接跳过拦截器
postcard.greenChannel(); // Provider should skip all of interceptors
break;
case FRAGMENT:
//如果是Fragment类型的直接跳过拦截器
postcard.greenChannel(); // Fragment needn't interceptors
default:
break;
}
}
}
_ARouter.getInstance().navigation(service),方法最后 return (T) postcard.getProvider(); 这个Provider就是我们自己定义的Provider(PathReplaceServiceImpl,他会走到 case PROVIDER:分支,检测instance是否存在,如果不存在反射创建 我们自定义的PathReplaceServiceImpl,然后调用它的init()初始化方法,为postcard设置Provider,代码返回到_ARouter的navigation方法,它会将刚开始复制的Provider返回 return (T) postcard.getProvider();返回到_ARtouter的build方法、
/**
* Build postcard by path and default group
*/
protected Postcard build(String path) {
if (TextUtils.isEmpty(path)) {
throw new HandlerException(Consts.TAG + "Parameter is invalid!");
} else {
PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
if (null != pService) {
//返回到这里
path = pService.forString(path);
}
return build(path, extractGroup(path));
}
}
path = pService.forString(path);会调用自定义的PathReplaceServiceImpl的forString(),这里我们可以拦截路由并返回处理后的路径给path。到这里我们分析完了ARouter.getInstance().build(main/about)。下面开始分析ARouter.getInstance().build(main/about)返回PostCard调用navigation()的过程
------------- ARouter.getInstance().build(/main/about) end -------------
------------- ARouter.getInstance().build(/main/about).navigation() start ------------- ARouter.getInstance().build(/main/about) 返回了自定义路由处理后的PostCard,PostCard调用navigation()会调用到
_ARouter.java
/**
* Use router navigation.
*
* @param context Activity or null.
* @param postcard Route metas
* @param requestCode RequestCode
* @param callback cb
*/
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
//提前处理路由
PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
if (null != pretreatmentService && !pretreatmentService.onPretreatment(context, postcard)) {
// Pretreatment failed, navigation canceled.
return null;
}
try {
LogisticsCenter.completion(postcard);
} catch (NoRouteFoundException ex) {
logger.warning(Consts.TAG, ex.getMessage());
if (debuggable()) {
// Show friendly tips for user.
runInMainThread(new Runnable() {
@Override
public void run() {
Toast.makeText(mContext, "There's no route matched!\n" +
" Path = [" + postcard.getPath() + "]\n" +
" Group = [" + postcard.getGroup() + "]", Toast.LENGTH_LONG).show();
}
});
}
//如果callback不为null调用callback
if (null != callback) {
callback.onLost(postcard);
//否则执行降级操作
} else {
// No callback for this invoke, then we use the global degrade service.
DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);
if (null != degradeService) {
degradeService.onLost(context, postcard);
}
}
return null;
}
if (null != callback) {
//调用callback的onFound方法
callback.onFound(postcard);
}
//如果没有这是greenChannel那么需要调拦截器,拦截器需要执行在子线程以免阻塞主线程,造ANR
if (!postcard.isGreenChannel()) { // It must be run in async thread, maybe interceptor cost too mush time made ANR.
interceptorService.doInterceptions(postcard, new InterceptorCallback() {
/**
* Continue process
*
* @param postcard route meta
*/
@Override
public void onContinue(Postcard postcard) {
_navigation(context, postcard, requestCode, callback);
}
/**
* Interrupt process, pipeline will be destory when this method called.
*
* @param exception Reson of interrupt.
*/
@Override
public void onInterrupt(Throwable exception) {
if (null != callback) {
callback.onInterrupt(postcard);
}
logger.info(Consts.TAG, "Navigation failed, termination by interceptor : " + exception.getMessage());
}
});
} else {
return _navigation(context, postcard, requestCode, callback);
}
return null;
}
PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);这个方法用于在调用路由前做一些我们自定义的操作,需要我们实现PretreatmentService,代码如下
PretreatmentServiceImpl.java
@Route(path = "/pre/service")
class PretreatmentServiceImpl : PretreatmentService {
override fun onPretreatment(context: Context?, postcard: Postcard?): Boolean {
Log.d("yyy","PretreatmentServiceImpl postcard = {$postcard}")
return true
}
override fun init(context: Context?) {
Log.d("yyy","PretreatmentServiceImpl content")
}
}
如果onPretreatment返回的是false那么不会触路由,然后触发LogisticsCenter.completion(postcard);组装PostCard,这里注意catch代码块,如果组装PostCard出现异常,并且没有设置callback,可以做降级操作,代码如下
if (null != callback) {
callback.onLost(postcard);
} else {
// No callback for this invoke, then we use the global degrade service.
DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);
if (null != degradeService) {
degradeService.onLost(context, postcard);
}
}
如果没有设置greenchannel那么会调用拦截器,拦截器是执行在子线程中,以防止阻塞主线程造成ANR,我们定义一个拦截器
//这里我们可以设置优先级
@Interceptor(priority = 1)
class InterceptorImpl :IInterceptor{
override fun process(postcard: Postcard?, callback: InterceptorCallback?) {
Log.d("yyy","postcard = ${postcard}")
//当执行完拦截器逻辑后调用,去执行下一个拦截器,或者继续之前流程
callback?.onContinue(postcard)
}
override fun init(context: Context?) {
Log.d("yyy","InterceptorImpl init")
}
}
拦截器执行代码:
InterceptorServiceImpl.java
@Route(path = "/arouter/service/interceptor")
public class InterceptorServiceImpl implements InterceptorService {
private static boolean interceptorHasInit;
private static final Object interceptorInitLock = new Object();
//执行路由时如果没有设置greenchannel会调用此方法
@Override
public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) {
//如果用户设置拦截器,启动拦截器
if (null != Warehouse.interceptors && Warehouse.interceptors.size() > 0) {
//检测拦截器状态,这里线程被wait住了
checkInterceptorsInitStatus();
//如果初始化时间过长调动callback.onInterrupt()表示初始化时间过长
if (!interceptorHasInit) {
callback.onInterrupt(new HandlerException("Interceptors initialization takes too much time."));
return;
}
//执行拦截器逻辑
LogisticsCenter.executor.execute(new Runnable() {
@Override
public void run() {
//使用CountDownLatch控制拦截器完场进度
CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size());
try {
//执行
_excute(0, interceptorCounter, postcard);
//拦截器执行完所有的任务
interceptorCounter.await(postcard.getTimeout(), TimeUnit.SECONDS);
if (interceptorCounter.getCount() > 0) { // Cancel the navigation this time, if it hasn't return anythings.
callback.onInterrupt(new HandlerException("The interceptor processing timed out."));
} else if (null != postcard.getTag()) { // Maybe some exception in the tag.
callback.onInterrupt(new HandlerException(postcard.getTag().toString()));
} else {
//继续流程
callback.onContinue(postcard);
}
} catch (Exception e) {
//出错抛出异常
callback.onInterrupt(e);
}
}
});
} else {
//没有设置拦截器,继续流程
callback.onContinue(postcard);
}
}
/**
* Excute interceptor
*
* @param index current interceptor index
* @param counter interceptor counter
* @param postcard routeMeta
*/
private static void _excute(final int index, final CancelableCountDownLatch counter, final Postcard postcard) {
if (index < Warehouse.interceptors.size()) {
//取出拦截器
IInterceptor iInterceptor = Warehouse.interceptors.get(index);
//执行拦截器的precess方法
iInterceptor.process(postcard, new InterceptorCallback() {
//我们自己在实现拦截器的时候会调用callback?.onContinue(postcard)然后会调用到这个方法
@Override
public void onContinue(Postcard postcard) {
// Last interceptor excute over with no exception
//一个拦截器执行完调用CountDownLatch.countDown()
counter.countDown();
//执行下一个拦截器
_excute(index + 1, counter--, postcard); // When counter is down, it will be execute continue ,but index bigger than interceptors size, then U know.
}
@Override
public void onInterrupt(Throwable exception) {
// Last interceptor excute over with fatal exception.
postcard.setTag(null == exception ? new HandlerException("No message.") : exception.getMessage()); // save the exception message for backup.
counter.cancel();
// Be attention, maybe the thread in callback has been changed,
// then the catch block(L207) will be invalid.
// The worst is the thread changed to main thread, then the app will be crash, if you throw this exception!
// if (!Looper.getMainLooper().equals(Looper.myLooper())) { // You shouldn't throw the exception if the thread is main thread.
// throw new HandlerException(exception.getMessage());
// }
}
});
}
}
//初始化拦截器,反射创建拦截器对象,初始化完场后notifyAll,执行拦截器逻辑
@Override
public void init(final Context context) {
//出
LogisticsCenter.executor.execute(new Runnable() {
@Override
public void run() {
if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) {
for (Map.Entry<Integer, Class<? extends IInterceptor>> entry : Warehouse.interceptorsIndex.entrySet()) {
Class<? extends IInterceptor> interceptorClass = entry.getValue();
try {
IInterceptor iInterceptor = interceptorClass.getConstructor().newInstance();
iInterceptor.init(context);
Warehouse.interceptors.add(iInterceptor);
} catch (Exception ex) {
throw new HandlerException(TAG + "ARouter init interceptor error! name = [" + interceptorClass.getName() + "], reason = [" + ex.getMessage() + "]");
}
}
interceptorHasInit = true;
logger.info(TAG, "ARouter interceptors init over.");
synchronized (interceptorInitLock) {
interceptorInitLock.notifyAll();
}
}
}
});
}
//拦截器如果未初始化完成会一直wait在这里
private static void checkInterceptorsInitStatus() {
synchronized (interceptorInitLock) {
while (!interceptorHasInit) {
try {
interceptorInitLock.wait(10 * 1000);
} catch (InterruptedException e) {
throw new HandlerException(TAG + "Interceptor init cost too much time error! reason = [" + e.getMessage() + "]");
}
}
}
}
}
执行完拦截器后继续流程代码,会调用 _navigation(context, postcard, requestCode, callback);源码:
private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
final Context currentContext = null == context ? mContext : context;
//这里开始判断postcard类型
switch (postcard.getType()) {
//Activity设置启动的intent,并且把页面参数设置到intent中,如果Context不是Activity类型,需要设置flag,最后显示启动Activity
case ACTIVITY:
// Build intent 这里创建Intent postcard.getDestination()存储的是要启动的目标Activity
final Intent intent = new Intent(currentContext, postcard.getDestination());
intent.putExtras(postcard.getExtras());
// Set flags.
int flags = postcard.getFlags();
if (-1 != flags) {
intent.setFlags(flags);
} else if (!(currentContext instanceof Activity)) { // Non activity, need less one flag.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
// Set Actions
String action = postcard.getAction();
if (!TextUtils.isEmpty(action)) {
intent.setAction(action);
}
// Navigation in main looper.
runInMainThread(new Runnable() {
@Override
public void run() {
startActivity(requestCode, currentContext, intent, postcard, callback);
}
});
break;
//如果返回Provider
case PROVIDER:
return postcard.getProvider();
case BOARDCAST:
case CONTENT_PROVIDER:
//如果返回Fragment
case FRAGMENT:
Class fragmentMeta = postcard.getDestination();
try {
Object instance = fragmentMeta.getConstructor().newInstance();
if (instance instanceof Fragment) {
((Fragment) instance).setArguments(postcard.getExtras());
} else if (instance instanceof android.support.v4.app.Fragment) {
((android.support.v4.app.Fragment) instance).setArguments(postcard.getExtras());
}
return instance;
} catch (Exception ex) {
logger.error(Consts.TAG, "Fetch fragment instance error, " + TextUtils.formatStackTrace(ex.getStackTrace()));
}
case METHOD:
case SERVICE:
default:
return null;
}
return null;
}
startActivity源码:
_ARouter.java
/**
* Start activity
*
* @see ActivityCompat
*/
private void startActivity(int requestCode, Context currentContext, Intent intent, Postcard postcard, NavigationCallback callback) {
//有返回码需要startActivityForResult
if (requestCode >= 0) { // Need start for result
if (currentContext instanceof Activity) {
ActivityCompat.startActivityForResult((Activity) currentContext, intent, requestCode, postcard.getOptionsBundle());
} else {
logger.warning(Consts.TAG, "Must use [navigation(activity, ...)] to support [startActivityForResult]");
}
} else {
//没有有返回码直接启动
ActivityCompat.startActivity(currentContext, intent, postcard.getOptionsBundle());
}
//设置启动和退出动画
if ((-1 != postcard.getEnterAnim() && -1 != postcard.getExitAnim()) && currentContext instanceof Activity) { // Old version.
((Activity) currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim());
}
if (null != callback) { // Navigation over.
//调用回调
callback.onArrival(postcard);
}
}
------------- ARouter.getInstance().build(/main/about).navigation() end -------------
3.5 启动页面总结
启动页面是ARouter路由的做最主要功能所以也是功能最复杂的
1、首先通过注解生成path和启动页面对应的关系
2、通过Tranform将对应关系初始化到ARouter中
3、ARouter.getInstance().build(/main/about)生成PostCard,如果自定义实现PathReplaceService那首先会进行路径解析
4、生成的Postcard调用navigation(),如果自定义实现了PretreatmentService那会首先执行预处理机制,在处理过程中如果有异常并且未实现Callback,会调用DegradeService做降级处理
5、如果实现了拦截器IInterceptor,拦截器可以设定优先级。注意这里的拦截器可能会发生阻塞,这样会导致主线程ANR,启动时可设置拦截器超时时间,ARouter的把拦截器的执行放在线程池中,线程池DefaultPoolExecutor核心线程数为内核数+1,最大线程数与核心线程数一致,这是因为所要执行的任务是CPU密集型任务,阻塞队列为ArrayBlockingQueue,大小为64。拦截器在执行拦截任务时,是阻塞的,使用的是CountDownLatch,当所有的拦截任务都执行完后开始执行启动Activity任务
6,组装用于启动目标Activity的Intent,设置传参,如果返回码不为0,使用startActivityForReslut,如果设置动画那设置启动和关闭页面动画
4 依赖注入的实现和使用
4.1 在注册的页面中使用
@Route(path = "/order/commit_audit") //启动路由
class CommitAuditActivity : BaseActivity() {
@Autowired(name = EXTRA_ORDER_ID) //依赖注入的成员变量需要有这个注解来修饰
@JvmField //示例代码是Kotlin代码所以使用这个注解修饰
var orderId: String? = null
·····
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ARouter.getInstance().inject(this) //需要调用这个方法才能注入
·····
}
}
4.2 注解后ARouter会自动生成
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class CommitAuditActivity$$ARouter$$Autowired implements ISyringe {
private SerializationService serializationService;
@Override
public void inject(Object target) {
serializationService = ARouter.getInstance().navigation(SerializationService.class);
CommitAuditActivity substitute = (CommitAuditActivity)target;
substitute.orderId = substitute.getIntent().getStringExtra("orderId");
}
}
这样启动的的时候就会自动注入了
5 依赖注入源码解析
5.1 标记注入变量
使用@Autowired(name = EXTRA_ORDER_ID)注解注释的为需要注入的字段
5.2 解析注入变量
生成类和ARouter注解的生成类似,但使用的是AutowiredProcessor这个解析注解的类
5.3 将生成的类注入到ARouter中
注入是从ARouter.getInstance().inject(this)开始的,最后会调用到
_ARouter
static void inject(Object thiz) {
AutowiredService autowiredService = ((AutowiredService) ARouter.getInstance().build("/arouter/service/autowired").navigation());
if (null != autowiredService) {
autowiredService.autowire(thiz);
}
}
去加载ARouter提前给我们注册好的AutowiredService,我们来看一下AutowiredService的实现
AutowiredServiceImpl.java
/**
* Autowired service impl.
*
* @author zhilong <a href="mailto:zhilong.lzl@alibaba-inc.com">Contact me.</a>
* @version 1.0
* @since 2017/2/28 下午6:08
*/
@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) {
//初始化LruCache和blackList
classCache = new LruCache<>(66);
blackList = new ArrayList<>();
}
@Override
public void autowire(Object instance) {
//这个instance是ARouter.getInstance().inject(this)的this,也就是我们需要注入的对象,取出类名称
String className = instance.getClass().getName();
try {
if (!blackList.contains(className)) {
//先从LruCache中查找注入依赖的信息ISyringe
ISyringe autowiredHelper = classCache.get(className);
if (null == autowiredHelper) { // No cache.
//LruCache中没有那么开始拼接注入需要依赖的信息
autowiredHelper = (ISyringe) Class.forName(instance.getClass().getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance();
}
//反射创建完注入依赖信息后,调用inject注入信息
autowiredHelper.inject(instance);
//添加到cache中
classCache.put(className, autowiredHelper);
}
} catch (Exception ex) {
blackList.add(className); // This instance need not autowired.
}
}
}
autowiredHelper.inject(instance);这句是关键他还会调用到ARouter为我们自动生成的类的inject
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class CommitAuditActivity$$ARouter$$Autowired implements ISyringe {
private SerializationService serializationService;
@Override
public void inject(Object target) {
//如果需要序列化那需要实现SerializationService
serializationService = ARouter.getInstance().navigation(SerializationService.class);
//转换目标对象
CommitAuditActivity substitute = (CommitAuditActivity)target;
//将注入的值取出,然后注入到目标对象中
substitute.orderId = substitute.getIntent().getStringExtra("orderId");
}
}
这样就可以注入到目标对象的成员变量中
5.4 依赖注入总结
1,注解标记需要注入的成员变量,生成注入依赖的类
2,ARouter.getInstance().inject(this)调用AutowiredService反射创建注入依赖类对象
3,调用ISyringe的inject()方法,将注入的值注入到目标对象中