ARouter的navigation过程
之前讲了初始化流程,现在接着看navigation过程,先来一个使用示例 后面好举例
@Route(path = "/image/imageActivity")
class MainActivity : AppCompatActivity() {
@Autowired(name = "tip")
@JvmField
var mTip: String? = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ARouter.getInstance().inject(this)
setContentView(R.layout.layout_activity_main)
findViewById<TextView>(R.id.mTvImageModule).setOnClickListener {
ARouter.getInstance().build("/login/loginActivity").navigation(this)
}
}
}
1.postcard制作过程
postcard何许人也,翻译是明信片,也就是路由信息类,里面存着路由数据uri, 携带参数,路径等等
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
if (null != pretreatmentService && !pretreatmentService.onPretreatment(context, postcard)) {
// Pretreatment failed, navigation canceled.
return null;
}
// Set context to postcard.
postcard.setContext(null == context ? mContext : context);
try {
LogisticsCenter.completion(postcard);
}
//省略代码
return null;
}
postcard保存了所有跳转类相关信息
1.设置postcard的context
2.调用LogisticsCenter.completion完善postcard信息
2.完善postcard信息
2.1 @Route生成的映射类(方便举例说明)
public class ARouter$$Group$$image implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put("/image/imageActivity", RouteMeta.build(RouteType.ACTIVITY, MainActivity.class, "/image/imageactivity", "image", new java.util.HashMap<String, Integer>(){{put("tip", 8); }}, -1, -2147483648));
}
}
2.2 完善postcard过程 稍长 忍一下
public synchronized static void completion(Postcard postcard) {
if (null == postcard) {
throw new NoRouteFoundException(TAG + "No postcard!");
}
//通过路由信息查找路由映射数据,第一次调用该分组下的路由的相关方法routeMeta一定是空,
//因为映射表还没加载过该组下的任何路由信息,也就是2.1部分的loadInto还没调用过,没有
//保存RouteMeta信息到集合中
RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
if (null == routeMeta) {
//第一次调用目标路由走到这里
//查找分组表信息,在之前文章有介绍,初始化过程会加载分组信息
if (!Warehouse.groupsIndex.containsKey(postcard.getGroup())) {
//找不到分组抛出异常
throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");
} else {
//找到分组
try {
//省略代码
//这一步,将调用目标组下的ARouter\$Group\$XX类文件,也就是2.1的代码
//将路径映射的类加载到WareHouse的集合中,
//下面有贴出代码addRouteGroupDynamic的实现过程
addRouteGroupDynamic(postcard.getGroup(), null);
//省略代码
} catch (Exception e) {
throw new HandlerException(TAG + "Fatal exception when loading group meta. [" + e.getMessage() + "]");
}
//再次调用自己,这一次因为将数据加载到集合中了,
//所以这次就会走到下面的else分支
completion(postcard); // Reload
} else {
//填充postcard数据
postcard.setDestination(routeMeta.getDestination());
postcard.setType(routeMeta.getType());
postcard.setPriority(routeMeta.getPriority());
postcard.setExtra(routeMeta.getExtra());
//省略uri处理过程
//Provider和Fragment设置为greenChannel(绿色通道会跳过拦截器处理过程)
switch (routeMeta.getType()) {
//如果是Provider类型 也就是我们定义的IProvider对象
case PROVIDER:
//从集合中查找对象,有就取出实例对象
Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
IProvider instance = Warehouse.providers.get(providerMeta);
if (null == instance) {
//不存在 反射创建对象,保存到Warehouse统一管理
IProvider provider;
try {
provider = providerMeta.getConstructor().newInstance();
provider.init(mContext);
Warehouse.providers.put(providerMeta, provider);
instance = provider;
} catch (Exception e) {
logger.error(TAG, "Init provider failed!", e);
throw new HandlerException("Init provider failed!");
}
}
//添加到postcard
postcard.setProvider(instance);
postcard.greenChannel(); // Provider should skip all of interceptors
break;
case FRAGMENT:
postcard.greenChannel(); // Fragment needn't interceptors
default:
break;
}
}
}
}
public synchronized static void addRouteGroupDynamic(String groupName, IRouteGroup group) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
if (Warehouse.groupsIndex.containsKey(groupName)){
//找到相关组,调用这个组映射的类,也就是上面贴出来的2.1部分@Route生成的类
//调用该类的loadInto将路由映射数据添加到集合中保存
Warehouse.groupsIndex.get(groupName).getConstructor().newInstance().loadInto(Warehouse.routes);
//loadInto调用过了 就不需要保留分组表中该分组信息了,移除掉,省点内存
Warehouse.groupsIndex.remove(groupName);
}
// cover old group.
if (null != group) {
group.loadInto(Warehouse.routes);
}
}
3.导航处理流程
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
if (null != pretreatmentService && !pretreatmentService.onPretreatment(context, postcard)) {
// Pretreatment failed, navigation canceled.
return null;
}
//添加context信息到postcard
postcard.setContext(null == context ? mContext : context);
try {
//前面介绍的完善postcard过程 不必多说了
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();
}
});
}
//回调通知onLost()
if (null != callback) {
callback.onLost(postcard);
} else {
// 全局的降级处理服务,在这里可以做toast提示错误之类
DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);
if (null != degradeService) {
degradeService.onLost(context, postcard);
}
}
return null;
}
//这里回调找到目标的通知
if (null != callback) {
callback.onFound(postcard);
}
//绿色通道跳过拦截器
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(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(postcard, requestCode, callback);
}
return null;
}
4.不同类型路由匹配处理流程
private Object _navigation(final Postcard postcard, final int requestCode, final NavigationCallback callback) {
final Context currentContext = postcard.getContext();
//根据类型 处理不同
switch (postcard.getType()) {
case ACTIVITY:
//Activity跳转 通过Intent跳到目标Activity
//看下前面@Route生成的类, 保存的有class对象
final Intent intent = new Intent(currentContext, postcard.getDestination());
//参数传递
intent.putExtras(postcard.getExtras());
// 设置Flags 比如启动模式之类
int flags = postcard.getFlags();
if (0 != flags) {
intent.setFlags(flags);
}
// 如果context不是Activity,需要加上NEW_TASK,
//因为Application和Service没有Activity栈
if (!(currentContext instanceof Activity)) {
intent.addFlags(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() {
//启动Activity
startActivity(requestCode, currentContext, intent, postcard, callback);
}
});
break;
case PROVIDER:
//如果是Provider,返回之前填充到postcard保存的IProvider对象,
//这样调用者就可以调用IProvider定义的方法
return postcard.getProvider();
case BOARDCAST:
case CONTENT_PROVIDER:
case FRAGMENT:
//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;
}
总结
navigation的调用流程就结束了,原理还是比较简单,代码过程也比较线性,容易理解,如有疑问,欢迎提出