上篇文章中,我们分析了如何将路由表单加载到内存中,这篇文章我们将分析如何根据这些路由表单,进行相应的跳转。
HelloService service = ARouter.getInstance().navigation(HelloService.class);
通过Class的方法进行跳转,现仅用作IProvider的返回。来看navigation()
protected T navigation(Class extends T> service) {
Postcard postcard = LogisticsCenter.buildProvider(service.getName());
//...
LogisticsCenter.completion(postcard);
return (T) postcard.getProvider();
}
可以看到,主要就是这三行代码。
把请求封装成postcard对象,方便后续调用
处理postcard,对进行赋值。同时,如果是provider,并且provider实例还未创建,那么会创建provider实例并调用其init方法,并把实例和postcard进行关联。
public synchronized static void completion(Postcard postcard) {
RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
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 resultMap = TextUtils.splitQueryParameters(rawUri);
Map paramsType = routeMeta.getParamsType();
if (MapUtils.isNotEmpty(paramsType)) {
// Set value by its type, just for params which annotation by @Param
for (Map.Entry params : paramsType.entrySet()) {
setValue(postcard,
params.getValue(),
params.getKey(),
resultMap.get(params.getKey()));
}
// Save params name which need autoinject.
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 be implememt 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;
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(); // Prorider跳过所有的interceptor
break;
case FRAGMENT:
postcard.greenChannel(); // Fragment跳过所有的interceptor
default:
break;
}
}
返回postcatd的IProvider对象。
ARouter.getInstance().build("/test/activity2").navigation(); //activity跳转
HelloService service = ((HelloService) ARouter.getInstance().build("/service/hello").navigation()); //获取Service
URL跳转,经过一系列navigation包装的方法,最终最调用
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
//处理postcard
LogisticsCenter.completion(postcard);
//...
callback.onFound(postcard);
//isGreenChannel為ture,說明不需要interceptor,要跳過interceptor
//无论是否调用interceptorService,最终,都会调用_navigation
if (!postcard.isGreenChannel()) {
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);
}
logger.info(Consts.TAG, "Navigation failed, termination by interceptor : " + exception.getMessage());
}
});
} else {
return _navigation(context, postcard, requestCode, callback);
}
return null;
}
可以看到,这里,无论是否调用interceptorService,最终,都会调用_navigation,_navigation是ARouter跳转的核心方法。
private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
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);
}
// Navigation in main looper.
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
if (requestCode > 0) { // Need start for result
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) { // Old version.
((Activity) currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim());
}
if (null != callback) { // Navigation over.
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;
}
可以看到,如果是Activity,则构建Intent,(如果有转场动画,那么会调用overridePendingTransition),并通过startActivity进行跳转。
如果是Provider,那么会返回postcard的provider对象。
如果是Fragment,则会通过构造方法反射一个实例,并通过setArguments将参数传递给Fragment
至此,ARouter的路由跳转过程就分析完了,总得来说,无非就是先封装成Postcard对象,再根据Postcard来进行相应跳转。
下篇文章我们来分析下ARouter interceptor 拦截器的初始化及其拦截过程。