ARouter简单分析

一、ARouter基本使用方法 ARouter初始化

ARouter.openDebug(); ARouter.init(getApplication());

1、Actvity跳转 定义换一个Actvity的@Route
@Route(path = "/test/activity1", name = "测试用 Activity") public class Test1Activity extends AppCompatActivity {@Autowired(desc = "姓名") String name = "jack"; @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); setContentView(R.layout.activity_test1); ARouter.getInstance().inject(this); } }

ARouter跳转:
ARouter.getInstance() .build("/test/activity1") .withString("name", "老王") .navigation();

2、Provider的使用 HellopSevice.java
public interface HelloService extends IProvider { void sayHello(String name); }

HelloServiceImpl.java
用@Route定义一个路由,其基类是IProvider故其类型是一个Provider
@Route(path = "/yourservicegroupname/hello") public class HelloServiceImpl implements HelloService { Context mContext; @Override public void sayHello(String name) { Toast.makeText(mContext, "Hello " + name, Toast.LENGTH_SHORT).show(); }/** * Do your init work in this method, it well be call when processor has been load. * * @param context ctx */ @Override public void init(Context context) { mContext = context; Log.e("testService", HelloService.class.getName() + " has init."); } }

调用HelloService
((HelloService) ARouter.getInstance().build("/yourservicegroupname/hello").navigation()).sayHello("mike");

3、interceptor的使用 使用@Interceptor注解,定义一个Interceptor拦截器,自动会加入interceptors拦截器列表
@Interceptor(priority = 7) public class Test1Interceptor implements IInterceptor { Context mContext; /** * The operation of this interceptor. * * @param postcard meta * @param callback cb */ @Override public void process(final Postcard postcard, final InterceptorCallback callback) { if ("/test/activity4".equals(postcard.getPath())) {// 这里的弹窗仅做举例,代码写法不具有可参考价值 final AlertDialog.Builder ab = new AlertDialog.Builder(MainActivity.getThis()); ab.setCancelable(false); ab.setTitle("温馨提醒"); ab.setMessage("想要跳转到Test4Activity么?(触发了\"/inter/test1\"拦截器,拦截了本次跳转)"); ab.setNegativeButton("继续", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { callback.onContinue(postcard); } }); ab.setNeutralButton("算了", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { callback.onInterrupt(null); } }); ab.setPositiveButton("加点料", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { postcard.withString("extra", "我是在拦截器中附加的参数"); callback.onContinue(postcard); } }); MainLooper.runOnUiThread(new Runnable() { @Override public void run() { ab.create().show(); } }); } else { callback.onContinue(postcard); } }/** * Do your init work in this method, it well be call when processor has been load. * * @param context ctx */ @Override public void init(Context context) { mContext = context; Log.e("testService", Test1Interceptor.class.getName() + " has init."); } }

拦截器的监听
ARouter.getInstance() .build("/test/activity4") .navigation(this, new NavCallback() { @Override public void onArrival(Postcard postcard) {}@Override public void onInterrupt(Postcard postcard) { Log.d("ARouter", "被拦截了"); } });

二、ARouter的核心类 1、RouteMeta 存储一个路由的元信息
public class RouteMeta { private RouteType type; // Type of route private Element rawType; // Raw type of route private Class destination; // Destination private String path; // Path of route private String group; // Group of route private int priority = -1; // The smaller the number, the higher the priority private int extra; // Extra data private Map paramsType; // Param type private String name; private Map injectConfig; // Cache inject config.public RouteMeta() { } }

其中最主要的信息:
  • path 路由路径
  • group 路由分组
  • destination 目的地,即加载的类对象,可以是Activity、Provider、Fragment的子类
  • type 是哪种类型的路由:如Activity、Provider、Fragment
2、PostCard 明信片
public final class Postcard extends RouteMeta { // Base private Uri uri; private Object tag; // A tag prepare for some thing wrong. private Bundle mBundle; // Data to transform private int flags = -1; // Flags of route private int timeout = 300; // Navigation timeout, TimeUnit.Second private IProvider provider; // It will be set value, if this postcard was provider. private boolean greenChannel; private SerializationService serializationService; // Animation private Bundle optionsCompat; // The transition animation of activity private int enterAnim = -1; private int exitAnim = -1; public Object navigation(Context context, NavigationCallback callback) { return ARouter.getInstance().navigation(context, this, -1, callback); } }

postCard 继承自RouteMeta
又增加了一些额外的属性
  • Bundle mBundle :Activity跳转时 传递的参数
  • flags :Activity跳转时的flags标记
  • timeout :路由超时时间
  • enterAnim 和exitAnim 进入进出的动画
  • IProvider provider 缓存的provider对象
它的一个核心方法navigation 最终代理到了
ARouter.getInstance().navigation(context, this, -1, callback);
3、Warehouse 仓库类,它里面保存所有的路由信息集合
class Warehouse { // Cache route and metas static Map> groupsIndex = new HashMap<>(); static Map routes = new HashMap<>(); // Cache provider static Map providers = new HashMap<>(); static Map providersIndex = new HashMap<>(); // Cache interceptor static Map> interceptorsIndex = new UniqueKeyTreeMap<>("More than one interceptors use same priority [%s]"); static List interceptors = new ArrayList<>(); static void clear() { routes.clear(); groupsIndex.clear(); providers.clear(); providersIndex.clear(); interceptors.clear(); interceptorsIndex.clear(); } }

  • groupsIndex 保存所有的分组
static Map> groupsIndex = new HashMap<>();

  • routes缓存所有的路由信息。但是分级缓存的,用到一个IRouteGroup分组时,就将该分组中的路由信息加载到routes中。
static Map routes = new HashMap<>();

  • providersIndex 缓存的是provider的路由表(与routes会有部分重合),推测可能考虑到provider数量较少,为了加快查询速度,就直接将所有的provider路由一次性加载进了providersIndex
static Map providersIndex = new HashMap<>();

  • providers 缓存的是某个路由对应的provider的实例。以单例实现。
static Map providers = new HashMap<>();

  • interceptorsIndex 和interceptors 缓存的是所有的来拦截器
static Map> interceptorsIndex = new UniqueKeyTreeMap<>("More than one interceptors use same priority [%s]"); static List interceptors = new ArrayList<>();

WareHouse的加载过程如下:
Set routerMap; // It will rebuild router map every times when debuggable. if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) { logger.info(TAG, "Run with debug mode or new install, rebuild router map."); // These class was generated by arouter-compiler. routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE); if (!routerMap.isEmpty()) { context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply(); }PackageUtils.updateVersion(context); // Save new version name when router map update finishes. } else { logger.info(TAG, "Load router map from cache."); routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet())); }logger.info(TAG, "Find router map finished, map size = " + routerMap.size() + ", cost " + (System.currentTimeMillis() - startInit) + " ms."); startInit = System.currentTimeMillis(); for (String className : routerMap) { if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) { // 对RooT的处理 // This one of root elements, load root. ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex); } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) { // Load interceptorMeta //interceptor 的处理 ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex); } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) { // Load providerIndex //provider的处理 ((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex); } } }

public final class Consts { public static final String SDK_NAME = "ARouter"; public static final String TAG = SDK_NAME + "::"; public static final String SEPARATOR = "$$"; public static final String SUFFIX_ROOT = "Root"; public static final String SUFFIX_INTERCEPTORS = "Interceptors"; public static final String SUFFIX_PROVIDERS = "Providers"; public static final String SUFFIX_AUTOWIRED = SEPARATOR + SDK_NAME + SEPARATOR + "Autowired"; public static final String DOT = "."; public static final String ROUTE_ROOT_PAKCAGE = "com.alibaba.android.arouter.routes"; public static final String AROUTER_SP_CACHE_KEY = "SP_AROUTER_CACHE"; public static final String AROUTER_SP_KEY_MAP = "ROUTER_MAP"; public static final String LAST_VERSION_NAME = "LAST_VERSION_NAME"; public static final String LAST_VERSION_CODE = "LAST_VERSION_CODE"; }

【ARouter简单分析】可知此处 会一次性加载:
  • groupsIndex 分组路由
  • providersIndex provider路由
  • interceptorsIndex 所有的拦截器路由
注解自动生成类示例 ARouter简单分析
文章图片
image.png
  • ARouterapp 一共有几个分组
/** * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */ public class ARouter$$Root$$app implements IRouteRoot { @Override public void loadInto(Map> routes) { routes.put("test", ARouter$$Group$$test.class); routes.put("yourservicegroupname", ARouter$$Group$$yourservicegroupname.class); } }

ARoutertest test组内的所有路由
/** * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */ public class ARouter$$Group$$test implements IRouteGroup { @Override public void loadInto(Map atlas) { atlas.put("/test/activity1", RouteMeta.build(RouteType.ACTIVITY, Test1Activity.class, "/test/activity1", "test", new java.util.HashMap(){{put("ser", 9); put("ch", 5); put("fl", 6); put("dou", 7); put("boy", 0); put("url", 8); put("pac", 10); put("obj", 11); put("name", 8); put("objList", 11); put("map", 11); put("age", 3); put("height", 3); }}, -1, -2147483648)); atlas.put("/test/activity2", RouteMeta.build(RouteType.ACTIVITY, Test2Activity.class, "/test/activity2", "test", new java.util.HashMap(){{put("key1", 8); }}, -1, -2147483648)); atlas.put("/test/activity3", RouteMeta.build(RouteType.ACTIVITY, Test3Activity.class, "/test/activity3", "test", new java.util.HashMap(){{put("name", 8); put("boy", 0); put("age", 3); }}, -1, -2147483648)); atlas.put("/test/activity4", RouteMeta.build(RouteType.ACTIVITY, Test4Activity.class, "/test/activity4", "test", null, -1, -2147483648)); atlas.put("/test/fragment", RouteMeta.build(RouteType.FRAGMENT, BlankFragment.class, "/test/fragment", "test", null, -1, -2147483648)); atlas.put("/test/webview", RouteMeta.build(RouteType.ACTIVITY, TestWebview.class, "/test/webview", "test", null, -1, -2147483648)); } }

yourservicegroupname 组内所有的路由信息
public class ARouter$$Group$$yourservicegroupname implements IRouteGroup { @Override public void loadInto(Map atlas) { atlas.put("/yourservicegroupname/hello", RouteMeta.build(RouteType.PROVIDER, HelloServiceImpl.class, "/yourservicegroupname/hello", "yourservicegroupname", null, -1, -2147483648)); atlas.put("/yourservicegroupname/json", RouteMeta.build(RouteType.PROVIDER, JsonServiceImpl.class, "/yourservicegroupname/json", "yourservicegroupname", null, -1, -2147483648)); atlas.put("/yourservicegroupname/single", RouteMeta.build(RouteType.PROVIDER, SingleService.class, "/yourservicegroupname/single", "yourservicegroupname", null, -1, -2147483648)); } }

  • ARouterapp 所有的Provider路由
/** * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */ public class ARouter$$Providers$$app implements IProviderGroup { @Override public void loadInto(Map providers) { providers.put("com.alibaba.android.arouter.demo.testservice.HelloService", RouteMeta.build(RouteType.PROVIDER, HelloServiceImpl.class, "/yourservicegroupname/hello", "yourservicegroupname", null, -1, -2147483648)); providers.put("com.alibaba.android.arouter.facade.service.SerializationService", RouteMeta.build(RouteType.PROVIDER, JsonServiceImpl.class, "/yourservicegroupname/json", "yourservicegroupname", null, -1, -2147483648)); providers.put("com.alibaba.android.arouter.demo.testservice.SingleService", RouteMeta.build(RouteType.PROVIDER, SingleService.class, "/yourservicegroupname/single", "yourservicegroupname", null, -1, -2147483648)); } }

  • ARouterapp 所有的interceptor路由
public class ARouter$$Interceptors$$app implements IInterceptorGroup { @Override public void loadInto(Map> interceptors) { interceptors.put(7, Test1Interceptor.class); } }

4、内部核心类
  • ARouter - 核心逻辑的外观类,内部调用_ARouter
  • _ARouter - 内部ARouter的实现类,负责构造PostCard、navigation路由操作、拦截器处理。
  • LogisticsCenter 实现路由信息的加载和寻址(完善PostCard信息)
具体的路由过程,可以分为两步:
//(1)build() 通过path,构造出一个简易的PostCard对象,目前只包含分组和path信息 Postcard postcard =ARouter.getInstance() .build("/test/activity2"); //(2)调用navigation 去寻址。 postcard.navigation();

我们具体看navigation 方法会进入ARouter.getInstance().navigation
public Object navigation() { return navigation(null); }/** * Navigation to the route with path in postcard. * * @param context Activity and so on. */ public Object navigation(Context context) { return navigation(context, null); }/** * Navigation to the route with path in postcard. * * @param context Activity and so on. */ public Object navigation(Context context, NavigationCallback callback) { return ARouter.getInstance().navigation(context, this, -1, callback); }

ARouter.navigation() 最终进入_ARouter.getInstance().navigation
public final class ARouter { private ARouter() { }/** * Launch the navigation. * * @param mContext. * @param postcard. * @param requestCode Set for startActivityForResult * @param callbackcb */ public Object navigation(Context mContext, Postcard postcard, int requestCode, NavigationCallback callback) { return _ARouter.getInstance().navigation(mContext, postcard, requestCode, callback); } }

我们来看_ARouter的navigation方法
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) { PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class); try { //(1)首先补全postcard中的路由信息,最终要的是要补全destination 对应的类信息 LogisticsCenter.completion(postcard); } catch (NoRouteFoundException ex) {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(postcard); }//(2)然后是拦截器处理 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); }retur

(1)补全postcard中的路由信息,最重要的信息就是destination 路由对应的类信息和type 路由类型信息
LogisticsCenter.completion(postcard);

(2)处理拦截器
遍历所有拦截器,如果被拦截,则回调onInterrupt
interceptorService.doInterceptions(postcard, new InterceptorCallback() {@Override public void onContinue(Postcard postcard) { _navigation(context, postcard, requestCode, callback); }@Override public void onInterrupt(Throwable exception) { if (null != callback) { callback.onInterrupt(postcard); }}

通过拦截器处理的路由 会调用:_navigation()
private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) { final Context currentContext = null == context ? mContext : context; switch (postcard.getType()) { case ACTIVITY: // Build intent 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; case PROVIDER: return postcard.getProvider(); case BOARDCAST: case CONTENT_PROVIDER: 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; }

可以看到:
  • type = Actvity,实际上是做的actvity跳转操作
  • type = Provider, 实际是返回一个Provider单例对象
  • type = Fragment,实际返回的是新创建的Fragment实例(非单例)
三、AutoWired 参数自动注册是如何实现的
@Route(path = "/test/activity1", name = "测试用 Activity") public class Test1Activity extends AppCompatActivity {@Autowired(desc = "姓名") String name = "jack"; @Autowired int age = 10; @Autowired int height = 175; @Autowired(name = "boy", required = true) boolean girl; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test1); ARouter.getInstance().inject(this); } }

  • 使用@Autowired 标记一个需要自动注入的参数,会自动生成一个Actvity名Autowired 类
ARouter简单分析
文章图片
image.png
public class Test1Activity$$ARouter$$Autowired implements ISyringe { private SerializationService serializationService; @Override public void inject(Object target) { serializationService = ARouter.getInstance().navigation(SerializationService.class); Test1Activity substitute = (Test1Activity)target; substitute.name = substitute.getIntent().getExtras() == null ? substitute.name : substitute.getIntent().getExtras().getString("name", substitute.name); substitute.age = substitute.getIntent().getIntExtra("age", substitute.age); substitute.height = substitute.getIntent().getIntExtra("height", substitute.height); substitute.girl = substitute.getIntent().getBooleanExtra("boy", substitute.girl); substitute.ch = substitute.getIntent().getCharExtra("ch", substitute.ch); substitute.fl = substitute.getIntent().getFloatExtra("fl", substitute.fl); substitute.dou = substitute.getIntent().getDoubleExtra("dou", substitute.dou); substitute.ser = (com.alibaba.android.arouter.demo.testinject.TestSerializable) substitute.getIntent().getSerializableExtra("ser"); substitute.pac = substitute.getIntent().getParcelableExtra("pac"); if (null != serializationService) { substitute.obj = serializationService.parseObject(substitute.getIntent().getStringExtra("obj"), new com.alibaba.android.arouter.facade.model.TypeWrapper(){}.getType()); } else { Log.e("ARouter::", "You want automatic inject the field 'obj' in class 'Test1Activity' , then you should implement 'SerializationService' to support object auto inject!"); } if (null != serializationService) { substitute.objList = serializationService.parseObject(substitute.getIntent().getStringExtra("objList"), new com.alibaba.android.arouter.facade.model.TypeWrapper>(){}.getType()); } else { Log.e("ARouter::", "You want automatic inject the field 'objList' in class 'Test1Activity' , then you should implement 'SerializationService' to support object auto inject!"); } if (null != serializationService) { substitute.map = serializationService.parseObject(substitute.getIntent().getStringExtra("map"), new com.alibaba.android.arouter.facade.model.TypeWrapper>(){}.getType()); } else { Log.e("ARouter::", "You want automatic inject the field 'map' in class 'Test1Activity' , then you should implement 'SerializationService' to support object auto inject!"); } substitute.url = substitute.getIntent().getExtras() == null ? substitute.url : substitute.getIntent().getExtras().getString("url", substitute.url); substitute.helloService = ARouter.getInstance().navigation(HelloService.class); } }

其核心操作如下,就是从intent中提取参数,然后赋值到activity对应的变量上。
Test1Activity substitute = (Test1Activity)target; substitute.name = substitute.getIntent().getExtras() == null ? substitute.name : substitute.getIntent().getExtras().getString("name", substitute.name);

  • 执行注入的方法
ARouter.getInstance().inject(this);

ARouter.java
/** * Inject params and services. */ public void inject(Object thiz) { _ARouter.inject(thiz); }

_ARouter.java
static void inject(Object thiz) { AutowiredService autowiredService = ((AutowiredService) ARouter.getInstance().build("/arouter/service/autowired").navigation()); if (null != autowiredService) { autowiredService.autowire(thiz); } }

从上面可知 最终调用进了_ARouter的inject方法,执行了AutowiredService的autowire()方法
我们再看AutowiredService,它是Arouter内置的一个IProvider
@Route(path = "/arouter/service/autowired") public class AutowiredServiceImpl implements AutowiredService { private LruCache classCache; private List 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. } } }

其核心方法如下:
autowiredHelper = (ISyringe) Class.forName(instance.getClass().getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance(); autowiredHelper.inject(instance);

SUFFIX_AUTOWIRED 其实就是 Autowired
以Test1Activity为例,最终效果就是找到自动创建的
Test1ActivityAutowired类,然后执行inject()

    推荐阅读