ARouter源码解析03-路由跳转

上篇文章中,我们分析了如何将路由表单加载到内存中,这篇文章我们将分析如何根据这些路由表单,进行相应的跳转。

通过Class跳转

HelloService service = ARouter.getInstance().navigation(HelloService.class);  

通过Class的方法进行跳转,现仅用作IProvider的返回。来看navigation()

 protected <T> T navigation(Class<? extends T> service) {
     Postcard postcard = LogisticsCenter.buildProvider(service.getName());
     //...
     LogisticsCenter.completion(postcard);
     return (T) postcard.getProvider();
}  

可以看到,主要就是这三行代码。

Postcard postcard = LogisticsCenter.buildProvider(service.getName());

把请求封装成postcard对象,方便后续调用

LogisticsCenter.completion(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<String, String> resultMap = TextUtils.splitQueryParameters(rawUri);
        Map<String, Integer> paramsType = routeMeta.getParamsType();

        if (MapUtils.isNotEmpty(paramsType)) {
            // Set value by its type, just for params which annotation by @Param
            for (Map.Entry<String, Integer> 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;
    }
}

postcard.getProvider()

返回postcatd的IProvider对象。

通过URL跳转

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 拦截器的初始化及其拦截过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

氦客

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值