前言
Android app开发中,经常会用到组件化技术,具体表现就是将各个模块以module的方式集成在主模块(App壳)中,各个业务module之间代码独立,互不依赖。那业务模块在不存在依赖关系的情况下,如何进行数据交互呢?这就涉及到模块间通讯了。网上有很多开源的模块间通讯方案,例如EventBus,ARouter等,今天来分析一下ARouter源码。
用法
- 环境配置
build.gradle中添加依赖
api config.thirddependencies.arouter_api
annotationProcessor config.thirddependencies.arouter_compiler
- 在待启动的目标Activity添加注解
@Route(path = "/test/activity2")
public class Test2Activity extends AppCompatActivity {
@Autowired
String key1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test2);
}
}
- 启动目标Activity
ARouter.getInstance()
.build("/test/activity2")
.navigation();
源码分析
ARouter.getInstance()
.build("/test/activity2")调用的是_ARouter中的build方法,返回的是一个Postcard对象
/**
* Build postcard by uri
*/
protected Postcard build(Uri uri) {
if (null == uri || TextUtils.isEmpty(uri.toString())) {
throw new HandlerException(Consts.TAG + "Parameter invalid!");
} else {
PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
if (null != pService) {
uri = pService.forUri(uri);
}
return new Postcard(uri.getPath(), extractGroup(uri.getPath()), uri, null);
}
}
Postcard调用navigation()方法, 内部其实是调用_ARouter的navigation(),
/**
* 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) {
try {
//首先对postcard进行一些处理,设置postcard的destination,type,priority 等一些属性值,completion()后面会有分析
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();
}
});
}
// 如果处理postcard失败,通过 callback 回调失败结果
// callback为空的情况下,如果有定义全局的降级处理(DegradeService),则使用全局处理
//降级处理也需要我们自己实现DegradeService接口
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;
}
//回调onFound
if (null != callback) {
callback.onFound(postcard);
}
//目前来说,PROVIDER服务类型,以及FRAGMENT类型不需要通过拦截器外,其他类型均需要通过拦截器
if (!postcard.isGreenChannel()) { // It must be run in async thread, maybe interceptor cost too mush time made ANR.
//如果需要拦截就执行onInterrupt(),否则执行onContinue,在onContinue中执行_navigation
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;
}
在_ARouter的navigation方法中
- 调用 LogisticsCenter.completion(postcard);这个方法主要做数据加载处理,执行完这个方法后,目标activity的路由信息就已经设置到postCard对象中了
- 当调用 LogisticsCenter.completion(postcard)出现异常的时候,判断是NavigationCallback callback参数是否为空,callback不为空的话直接回调callback.onLost(); callback为空的话,调用全局降级服务DegradeService.onLost(), 然后终止整个流程
- 判断postcard.isGreenChannel()是否需要执行拦截器逻辑,在拦截器中如果需要拦截,则回调onInterrupt(Throwable exception)方法,不需要拦截则会回调onContinue(Postcard postcard), 在onContinue方法中执行_navigation方法取执行Activity跳转逻辑
网友评论