WMRouter(1)-基本结构分析

作者: susion哒哒 | 来源:发表于2018-10-15 19:06 被阅读13次

文章是作者学习WMRouter的源码的重点纪要。 WMRouter官方文档 : https://mp.weixin.qq.com/s/pKRi5qpZmol7xFIfeBbK_A

本文整理一下WMRouter的基本路由逻辑,并剖析相关路由类的设计。作者巧妙的使用继承设计了整个WMRouter的路由体系,下面我们就从源码来看一下是如何实现的:

UriHandler

WMRouter中,对于每一个或每一类Uri都会有一个UriHandler来做处理,这个类定义了一个基本的处理逻辑。

该类处理Uri的入口方法为handle, 因此,理清它的主要处理逻辑,我们只需要看这个方法即可:

//处理URI。通常不需要覆写本方法。
public void handle(@NonNull final UriRequest request, @NonNull final UriCallback callback) {
    if (shouldHandle(request)) {
        if (mInterceptor != null && !request.isSkipInterceptors()) {
            mInterceptor.intercept(request, new UriCallback() { 
                @Override public void onNext() {
                    handleInternal(request, callback);
                }
                @Override public void onComplete(int result) {
                    callback.onComplete(result);
                }
            });
        } else {
            handleInternal(request, callback);
        }
    } else {
        callback.onNext();
    }
}

mInterceptorChainedInterceptor的实例,下面会介绍。

handle()具体处理逻辑如下图:

UriHandle.handle().png

UriInterceptor 与 ChainedInterceptor

UriInterceptor为设置给UriHandler的拦截器,在handleInternal方法之前调用。

    public interface UriInterceptor {
        void intercept(@NonNull UriRequest request, @NonNull UriCallback callback);
    }

UriHandler中的拦截器是ChainedInterceptor, ChainedInterceptor实现了UriInterceptor, 并含有一个UriInterceptor列表,即支持添加多个拦截器,来看一下核心实现:

    public void intercept(@NonNull UriRequest request, @NonNull UriCallback callback) {
        next(mInterceptors.iterator(), request, callback);  //对于链上的每一个 interceptor 都要调用一遍
    }

    private void next(@NonNull final Iterator<UriInterceptor> iterator, @NonNull final UriRequest request, @NonNull final UriCallback callback) {
        if (iterator.hasNext()) {
            iterator.next().intercept(request, new UriCallback() {
                @Override public void onNext() {
                    next(iterator, request, callback);
                }
                @Override public void onComplete(int resultCode) {
                    callback.onComplete(resultCode);
                }
            });
        } else {
            callback.onNext();
        }
    }

即,依次遍历每一个UriInterceptor,调用其intercept方法。需要注意的是callback.onComplete(resultCode)的调用,会导致路由的终止。

ChainedHandler

上面UriHandler是处理一个uri的hanler,比如 A Activity的路由为test://a,那么可以新建一个UriHandler来处理,而ChainedHandler则以列表组织多个UriHandler,每向ChainedHandler插入一个UriHandler可以指定一个优先级,优先级高的会被插入到列表前面。ChainedHandler复写了handleInternal方法:

    @Override
    protected void handleInternal(@NonNull final UriRequest request, @NonNull final UriCallback callback) {
        next(mHandlers.iterator(), request, callback);
    }

    private void next(@NonNull final Iterator<UriHandler> iterator, @NonNull final UriRequest request,
                      @NonNull final UriCallback callback) {
        if (iterator.hasNext()) {
            UriHandler t = iterator.next();
            t.handle(request, new UriCallback() {
                @Override
                public void onNext() {
                    next(iterator, request, callback);
                }
                @Override
                public void onComplete(int resultCode) {
                    callback.onComplete(resultCode);
                }
            });
        } else {
            callback.onNext();
        }
    }

ChainedHandler会逐一调用每个UriHandlerhandle方法。

上面我们了解了WMRouter中路由的基本组成元素UriHandlerUriInterceptorChainedHandlerChainedInterceptor, 接下来我们看下源码是如何使用它们构造路由体系的:

RootUriHandler

它继承自ChainedHandler,提供startUri(UriRequest)并传入RootUriCallback来作为一次路由的起点:

public void startUri(@NonNull UriRequest request) {
    //删除了一系列的判断条件
    handle(request, new RootUriCallback(request));
}

protected class RootUriCallback implements UriCallback {
    private final UriRequest mRequest;
    public RootUriCallback(UriRequest request) {
        mRequest = request;
    }

    @Override public void onNext() {
        onComplete(CODE_NOT_FOUND);
    }
    
    @Override public void onComplete(int resultCode) {
        switch (resultCode) {
            case CODE_REDIRECT:  // 重定向,重新跳转
                startUri(mRequest);
                break;
            case CODE_SUCCESS:
                mRequest.putField(UriRequest.FIELD_RESULT_CODE, resultCode);
                onSuccess(mRequest);
                break;
            default:
                mRequest.putField(UriRequest.FIELD_RESULT_CODE, resultCode);
                onError(mRequest, resultCode);
                break;
        }
    }
}

基于上面的设计,在WMRouter中路由的起点UriHandlerDefaultRootUriHandler,这个UriHandler在起始时添加了下面4个子Handler:

    public DefaultRootUriHandler(Context context,@Nullable String defaultScheme, @Nullable String defaultHost) {
        // 处理RouterPage注解定义的内部页面跳转
        addChildHandler(createPageAnnotationHandler(), 300);
        // 处理RouterUri注解定义的URI跳转,如果注解没定义,继续分发到后面的Handler
        addChildHandler(createUriAnnotationHandler(defaultScheme, defaultHost), 200);
        // 处理RouterRegex注解定义的正则匹配
        addChildHandler( createRegexAnnotationHandler(), 100);
        addChildHandler(new StartUriHandler(), -100);
    }

这几个子UriHandler当然也是继承自UriHandler, 对于每一个子Handler,下一节再分析。

经过上面的分析,我们大致可以总结WMRouter的路由过程:

WMRouter路由体系.png

读后感

可以看到作者基本上使用两个概念UriHandlerUriInterceptor就完成了整个设计。并再此基础上引入了ChainedHandlerChainedInterceptor,整体设计十分巧妙。
不过说实话,我在第一遍阅读这部分源码的时候ChainedHandlerUriHandler把我搅的是有点小头晕的。我想可能另一种设置思路如下:

我想象的组成结构WMRouter.png

相关文章

网友评论

    本文标题:WMRouter(1)-基本结构分析

    本文链接:https://www.haomeiwen.com/subject/lmkqzftx.html