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
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对象
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 所有的拦截器路由
文章图片
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实例(非单例)
@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 类
文章图片
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
其核心操作如下,就是从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()
推荐阅读
- 如何寻找情感问答App的分析切入点
- D13|D13 张贇 Banner分析
- 科学养胃,别被忽悠,其实真的很简单
- opencv|opencv C++模板匹配的简单实现
- 自媒体形势分析
- 松软可口易消化,无需烤箱超简单,新手麻麻也能轻松成功~
- 2020-12(完成事项)
- Android事件传递源码分析
- Python数据分析(一)(Matplotlib使用)
- 简单心理2019春A期+32+张荣