ARouter相关文章虽然对,作为学习笔记使用,有问题希望能够尽情提出,共同交流
蒋八九
@Override
public void onCreate() {
super.onCreate();
//官方建议推荐在Application中初始化
ARouter.init(this);
}
@Override
public void onTerminate() {
super.onTerminate();
ARouter.getInstance().destroy();
}
类必须注册路由地址
@Route(path = Constance.PATH_MAINACTIVITY)
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
注册路由
ARouter.getInstance().inject(this);
补充fragment的获取
Fragment thirdFragment = (Fragment) ARouter.getInstance().build(PATH_THIEDFRAGMENT).navigation();
getSupportFragmentManager().beginTransaction().replace(R.id.fird, thirdFragment).commitNow();
findViewById(R.id.mian_tv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
跳转路由
ARouter.getInstance().build(Constance.PATH_SECONDACTIVITY)
.withInt("id", 1)
.withString("key", "12345")
.withParcelable("person", new Person("蒋八九", 18))
.navigation(MainActivity.this, 123, new NavigationCallback() {
@Override
public void onFound(Postcard postcard) {
Log.e(TAG, "onFound:找到路由地址");
}
@Override
public void onLost(Postcard postcard) {
Log.e(TAG, "onLost:没找到路由地址");
}
@Override
public void onArrival(Postcard postcard) {
Log.e(TAG, "onArrival,跳转成功");
}
@Override
public void onInterrupt(Postcard postcard) {
Log.e(TAG, "onInterrupt:路由拦截");
}
});
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.e(TAG, "onActivityResult:requestCode" + requestCode + ";;;resultCode" + resultCode);
}
}
这里数字越小,优先级越大,类继承IInterceptor
@Interceptor(priority = -2)
public class BusinessInterceptor implements IInterceptor {
@Override
public void process(Postcard postcard, InterceptorCallback callback) {
if (postcard.getPath().equals(Constance.PATH_SECONDACTIVITY)) {
Log.e(TAG, "拦截 ,拦截后在navigationCallback中的onInterrupt中会回调,然后结束");
callback.onInterrupt(new Throwable("-----"));
}else{
Log.e(TAG, "继续往下执行跳转");
callback.onContinue(postcard);
}
}
@Override
public void init(Context context) {
Log.e(TAG, "UserInterceptor-拦截器-init: ");
}
}
APT——Android annotation processing tool,注解处理器,它用于在编译期扫描和处理注解,然后通过javapoet生成一个java文件,然后存放到指定的文件中。优点就是方便简单,少写很多代码。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Route {
String path();
}
1、将注解和javaPoet作为依赖添加进来
2、继承AbstractProcessor,重写init()、getSupportAnnotationTypes(),getSupportSourceVersion()、process()
添加依赖:
implementation 'com.alibaba:arouter-annotation:1.0' 自定义的注解
implementation 'com.squareup:javapoet:1.8.0' 这个是用来自动生成java文件的
AutoService固定写法,用来注册。
@AutoService(Processor.class)
支持的注解处理器类型,让注解处理器处理。
@SupportedAnnotationTypes(ANNOTATION_TYPE_INTECEPTOR)
public class InterceptorProcessor extends BaseProcessor {
private Map<Integer, Element> interceptors = new TreeMap<>();
private TypeMirror iInterceptor = null;
//文件生成器 类/资源,Filter用于创建新的源文件,class文件预计辅助文件
private Filer mFiler ;
//操作Elememts工具类(类、函数、属性都是Element)
private Elements elementUtils ;
//type(类信息)工具类,包含用于操作TypeMirror的工具方法
private Types typeUtils ;
在这里初始化一些工具类。主要用于一些初始化的操作,通过该方法的参数processingEnvironment可以获取一些有用的工具类
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
mFiler = processingEnv.getFiler();
types = processingEnv.getTypeUtils();
elementUtils = processingEnv.getElementUtils();
typeUtils = new TypeUtils(types, elementUtils);
iInterceptor = elementUtils.getTypeElement(Consts.IINTERCEPTOR).asType();
}
1、根据roundEvironment的getElementsAnnotationWith(注解.class)方法获取所有被该注解注释的元素。然后遍历所有elements元素,通过getAnnotation去获得所有注解接口,然后调用接口中的方法即可获得参数。
2、封装MethodSpec、封装TypeSpec,然后通过javaFile生成java文件并写入到file中。
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
if (CollectionUtils.isNotEmpty(annotations)) {
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Interceptor.class);
parseInterceptors(elements);
return true;
}
return false;
}
private void parseInterceptors(Set<? extends Element> elements) throws IOException {
for (Element element : elements) {
Interceptor interceptor = element.getAnnotation(Interceptor.class);
Element lastInterceptor = interceptors.get(interceptor.priority());
}
interceptors.put(interceptor.priority(), element);
}
TypeElement type_ITollgate = elementUtils.getTypeElement(IINTERCEPTOR);
TypeElement type_ITollgateGroup = elementUtils.getTypeElement(IINTERCEPTOR_GROUP);
ParameterizedTypeName inputMapTypeOfTollgate = ParameterizedTypeName.get(
ClassName.get(Map.class),
ClassName.get(Integer.class),
ParameterizedTypeName.get(
ClassName.get(Class.class),
WildcardTypeName.subtypeOf(ClassName.get(type_ITollgate))
)
);
ParameterSpec tollgateParamSpec = ParameterSpec.builder(inputMapTypeOfTollgate, "interceptors").build();
封装方法
MethodSpec.Builder loadIntoMethodOfTollgateBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
.addAnnotation(Override.class)
.addModifiers(PUBLIC)
.addParameter(tollgateParamSpec);
if (null != interceptors && interceptors.size() > 0) {
for (Map.Entry<Integer, Element> entry : interceptors.entrySet()) {
loadIntoMethodOfTollgateBuilder.addStatement("interceptors.put(" + entry.getKey() + ", $T.class)", ClassName.get((TypeElement) entry.getValue()));
}
}
封装类TypeSpec,然后通过javaFile整合类和方法生成java文件并写入file文件中。
JavaFile.builder(PACKAGE_OF_GENERATE_FILE,
TypeSpec.classBuilder(NAME_OF_INTERCEPTOR + SEPARATOR + moduleName)
.addModifiers(PUBLIC)
.addJavadoc(WARNING_TIPS)
.addMethod(loadIntoMethodOfTollgateBuilder.build())
.addSuperinterface(ClassName.get(type_ITollgateGroup))
.build()
).build().writeTo(mFiler);
}
}
ARouter:是个外观,里面的方法都是调用_ARouter来实现的,
_ARouter:外观模式模式,通过这个类统一调用Logger、LogisticsCenter的功能,为了实现外观模式,build和navigation的方法也通过ARouter中转一下。这个设计比较神奇。其中natigation方法是核心方法,postcard填充,callback回调,拦截器调用,降级策略、界面跳转都在这里实现。
LogisticsCenter:物流中心,主要方法是init(获取base.apk中以com.alibaba.android.arouter.routers开头的全类名,存入hashset缓存中)和complete(填充postcard)。
初始化主要目的是:获取关于router全类名的hashmap,然后填充warehouse中的map。
主要步骤是:
为什么只获取这三个并填充,因为有Routerroot就有分组,就能获取到其他需要跳转的具体类,其他的可能点击的时候才加载,所以不需要初始化的时候浪费那么多资源。
这使用前必须进行init操作,官方建议写在application中
ARouter.init(this);
public static void init(Application application) {
if (!hasInit) {
logger = _ARouter.logger;
_ARouter.logger.info(Consts.TAG, "ARouter init start.");
初始化ARouter
hasInit = _ARouter.init(application);
if (hasInit) {
初始化interceptor拦截器
_ARouter.afterInit();
}
}
}
_ARouter.java类ARouter core (Facade patten),是个外观模式,外观模式相当于util工具类,将杂七杂八的都封装起来,统一处理
final class _ARouter {
首先这里开了一个线程池,继承与ThreadPoolExecutor的核心线程和最大线程数相同都是cup核数+1,阻塞队列是ArrayBlockingQueue
private volatile static ThreadPoolExecutor executor = DefaultPoolExecutor.getInstance();
protected static synchronized boolean init(Application application) {
mContext = application;
Init方法最终是调用了Logistics Center的init方法来实现ARouter的初始化操作。
LogisticsCenter.init(mContext, executor);
hasInit = true;
return true;
}
}
LogisticsCenter(LogisticsCenter contain all of the map.)包含了所有的map,在这个init中完成ARouter的初始化工作,这里的主要目的:
1、遍历base.java中的左右全类名,取出以com.alibaba.android.arouter.routes开头的全类名放入hashset集合中并存放到sp的CASH中。
2、遍历hashset中的全类名,通过反射构造函数的方法分别得到IRouterRoot、IIterceptorGroup、IProviderGroup的实例,并通过loadInto方法,给WareHouse中的对应的map赋值。
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
mContext = context;
executor = tpe;
try {
Set<String> routerMap;
如果是debug模式或者是第一次使用ARouter进入;
if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
通过遍历base.apk中所有全类名,将以com.alibaba.android.arouter.routes开头的包名通通找出来,并封装成HashSet,当debug或者是第一次进入的时候,缓存进去,以后就直接获取使用。
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);
} else {
不是第一次进来直接从cash缓存中获取hashMap的值
routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>()));
}
获取到hashmap之后遍历,通过构造函数反射分别获取IRouteRoot、IInterceptorGroup、IProviderGroup的实例对象,然后调用对象中的loadInto方法,对WareHouse中的map进行赋值。
for (String className : routerMap) {
if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
}
}
} catch (Exception e) {
}
}
注册的主要目的是为了得到AutowiredServiceImpl实例,然后调用它的autowire方法完成传递值的自动装箱功能。
注册的主要步骤:
ARouter.getInstance().inject(this);
public void inject(Object thiz) {
_ARouter.inject(thiz);
}
biuld的作用是得到一个包含path和group的Postcard的构造。最后通过navigation方法执行。
static void inject(Object thiz) {
AutowiredService autowiredService = ((AutowiredService) ARouter.getInstance().build("/arouter/service/autowired").navigation());
if (null != autowiredService) {
autowiredService.autowire(thiz);
}
}
最后在navigation在_ARouter中执行,首先填充postcard。如果填充异常,则调用NavigationCallback的onLost方法,如果没有写这个回调方法,那么就通过全局降级。这里注册过程不涉及到这一步。
3. 在navigation中调用LogisticsCenter.complete()方法填充postCard,postcard是RouterMeta的子类,注册过程中主要做两件事。第一、填充destination、type、extra等基本参数;第二、根据注册的provider分支填充postcast的provider值得到AutowiredServiceImpl实例,同时开通绿色通道。
4. 最后调用_navigation()方法真正执行,注册过程中type类型直接走Provider分支,主要是为了得到post.getProvider()对象,也就是AutowiredServiceImpl对象。
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
try {
LogisticsCenter.completion(postcard);
} catch (NoRouteFoundException ex) {
if (null != callback) {
callback.onLost(postcard);
} else {
DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);
if (null != degradeService) {
degradeService.onLost(context, postcard);
}
}
return null;
}
if (null != callback) {
callback.onFound(postcard);
}
.............
return _navigation(context, postcard, requestCode, callback);
}
public synchronized static void completion(Postcard postcard) {
RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
if (null == routeMeta) {
Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup());
if (null == groupMeta) {
...........
} else {
try {
IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();
iGroupInstance.loadInto(Warehouse.routes);
Warehouse.groupsIndex.remove(postcard.getGroup());
} catch (Exception e) {
...........
}
completion(postcard);
}
} else {
postcard.setDestination(routeMeta.getDestination()); //填充XXX.class
postcard.setType(routeMeta.getType()); //填充类型,Activity还是Fragment
postcard.setPriority(routeMeta.getPriority()); //填充优先级,最小堆
postcard.setExtra(routeMeta.getExtra()); //填充传参
...........
switch (routeMeta.getType()) {
case PROVIDER:
Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
IProvider instance = Warehouse.providers.get(providerMeta);
if (null == instance) {
IProvider provider;
try {
provider = providerMeta.getConstructor().newInstance();
provider.init(mContext);
Warehouse.providers.put(providerMeta, provider);
instance = provider;
} catch (Exception e) {
throw new HandlerException("Init provider failed! " + e.getMessage());
}
}
postcard.setProvider(instance);
postcard.greenChannel();
break;
case FRAGMENT:
postcard.greenChannel();
default:
break;
}
}
}
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:
...............
break;
case PROVIDER:
return postcard.getProvider();注册过程中主要是为了得到AutowiredServiceimpl对象。
case BOARDCAST:
case CONTENT_PROVIDER:
case FRAGMENT:
...............
case METHOD:
case SERVICE:
default:
return null;
}
return null;
}
最后自动装箱功能通过autowire方法来实现。
public void autowire(Object instance) {
String className = instance.getClass().getName();
try {
if (!blackList.contains(className)) {
ISyringe autowiredHelper = classCache.get(className);
if (null == autowiredHelper) {
通过反射获取$$ARouter$$Autowired的对象,并强转为ISyring成功,表示该类中添加了Autowire的注解。
autowiredHelper = (ISyringe) Class.forName(instance.getClass().getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance();
}
获取成功,就调用inject方法实现传参的自动装箱功能。并将对象保存到缓存中。
autowiredHelper.inject(instance);
classCache.put(className, autowiredHelper);
}
} catch (Exception ex) {
如果没有@autowire注释,就将该类添加到黑名单,下次就不装箱了。依据是强转ISyring对象失败。
blackList.add(className);
}
}
跳转过程和注册过程相似,这里多了NavigationCallback和requestCode,而且type是Activity或者fragment。
ARouter.getInstance().build(Constance.PATH_SECONDACTIVITY)
.withInt("id", 1)
.withString("key", "12345")
.withParcelable("person", new Person("蒋八九", 18))
.navigation(MainActivity.this, 123, new NavigationCallback() {
@Override
public void onFound(Postcard postcard) {
postcard填充完毕,没有异常
}
@Override
public void onLost(Postcard postcard) {
如果postcard==null或者通过路由分组找不到路由组全类名
}
@Override
public void onArrival(Postcard postcard) {
最终startActivity结束,调用onArrival
}
@Override
public void onInterrupt(Postcard postcard) {
在自定义拦截器中调用interrupt方法
}
});
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
try {
这里填充postcard,fragment默认不拦截。
LogisticsCenter.completion(postcard);
} catch (NoRouteFoundException ex) {
if (null != callback) {
如果postcard==null或者在分组中找不到目标路由的全类名。在回调onLost方法通知
callback.onLost(postcard);
} else {
没有写回调,则进行降级
DegradeService degradeService=ARouter.getInstance().navigation(DegradeService.class);
if (null != degradeService) {
degradeService.onLost(context, postcard);
}
}
return null;
}
if (null != callback) {
填充postcard完成后,通知onFound
callback.onFound(postcard);
}
if (!postcard.isGreenChannel()) {
如果自定义了interceptor类,则执行拦截操作,PROVIDER和Fragment默认不进行拦截。
interceptorService.doInterceptions(postcard, new InterceptorCallback() {
@Override
public void onContinue(Postcard postcard) {
拦截完后调用onContinue方法继续执行
_navigation(context, postcard, requestCode, callback);
}
@Override
public void onInterrupt(Throwable exception) {
拦截完后调用onInterrupt方法通知用户
if (null != callback) {
callback.onInterrupt(postcard);
}}
});
} else {
return _navigation(context, postcard, requestCode, callback);
}
return null;
}
@Interceptor(priority = -2)
public class BusinessInterceptor implements IInterceptor {
@Override
public void process(Postcard postcard, InterceptorCallback callback) {
if (postcard.getPath().equals(Constance.PATH_SECONDACTIVITY)) {
callback.onInterrupt(new Throwable("拦截"));
}else{
Log.e(TAG, "继续执行跳转 ");
callback.onContinue(postcard);
}
}
@Override
public void init(Context context) {
Log.e(TAG, "UserInterceptor-拦截器-init: ");
}
}
不拦截或者拦截调用onContinue方法,才能完成最终的跳转_navigation方法。
对于Activity类:
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:
final Intent intent = new Intent(currentContext, postcard.getDestination());
intent.putExtras(postcard.getExtras());
int flags = postcard.getFlags();
if (-1 != flags) {
intent.setFlags(flags);
} else if (!(currentContext instanceof Activity)) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
if (requestCode > 0) {
ActivityCompat.startActivityForResult((Activity) currentContext, intent, requestCode, postcard.getOptionsBundle());
} else {
ActivityCompat.startActivity(currentContext, intent, postcard.getOptionsBundle());
}
if ((0 != postcard.getEnterAnim() || 0 != postcard.getExitAnim()) && currentContext instanceof Activity) {
((Activity) currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim());
}
if (null != callback) {
callback.onArrival(postcard);
}
}
});
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;
}
官方例子写法:继承DegradeService即可
@Route(path = Constance.PATH_MYDEGRADE_SERVICE)
public class MyDegradeService implements DegradeService {
@Override
public void onLost(Context context, Postcard postcard) {
Log.e("----", "onLost:全局降级策略 " );
}
@Override
public void init(Context context) {
}
}
依赖的注入就是自动装箱:autowired过程。
首先在arouter-api这个包中有个类叫做:AutowiredServiceImpl实现了Iprovider。并且添加了注释
@Route路径是arouter/service/autowired
@Route(path = "/arouter/service/autowired")
public class AutowiredServiceImpl implements AutowiredService {
...............
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.
}
}
}
因此这个类在编译的时候自动生成的类会添加到arouter分组中
public class ARouter\$\$Root\$\$arouterapi implements IRouteRoot {
@Override
public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) {
routes.put("arouter", ARouter\$\$Group\$\$arouter.class);
}
}
从这个分组中可以根据path获取AutowiredServiceImpl和InterceptorServiceImpl两个类。
public class ARouter\$\$Group\$\$arouter implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put("/arouter/service/autowired", RouteMeta.build(RouteType.PROVIDER, AutowiredServiceImpl.class, "/arouter/service/autowired", "arouter", null, -1, -2147483648));
atlas.put("/arouter/service/interceptor", RouteMeta.build(RouteType.PROVIDER, InterceptorServiceImpl.class, "/arouter/service/interceptor", "arouter", null, -1, -2147483648));
}
}
当在自定义的onCreate中添加ARouter.getInstance().inject(this)完成注入。这里根据path路径获取到AutowiredServiceImpl对象,最后调用其中的autowired方法,将this传入,通过this.getIntent()获取参数并赋值完成注入工作。
static void inject(Object thiz) {
AutowiredService autowiredService = ((AutowiredService) ARouter.getInstance().build("/arouter/service/autowired").navigation());
if (null != autowiredService) {
autowiredService.autowire(thiz);
}
}