/** * Completion the postcard by route metas * * @param postcard Incomplete postcard, should complete by this method. */ publicsynchronizedstaticvoidcompletion(Postcard postcard) { if (null == postcard) { thrownewNoRouteFoundException(TAG + "No postcard!"); }
switch (routeMeta.getType()) { case PROVIDER: // if the route is provider, should find its instance // Its provider, so it must implement IProvider Class<? extendsIProvider> providerMeta = (Class<? extendsIProvider>) routeMeta.getDestination(); IProviderinstance= 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) { thrownewHandlerException("Init provider failed! " + e.getMessage()); } } postcard.setProvider(instance); postcard.greenChannel(); // Provider should skip all of interceptors break; case FRAGMENT: postcard.greenChannel(); // Fragment needn't interceptors default: break; } } }
protected Object navigation(final Context context, final Postcard postcard, finalint requestCode, final NavigationCallback callback) {
...
if (!postcard.isGreenChannel()) { // It must be run in async thread, maybe interceptor cost too mush time made ANR. interceptorService.doInterceptions(postcard, newInterceptorCallback() { /** * Continue process * * @param postcard route meta */ @Override publicvoidonContinue(Postcard postcard) { _navigation(context, postcard, requestCode, callback); }
/** * Interrupt process, pipeline will be destory when this method called. * * @param exception Reson of interrupt. */ @Override publicvoidonInterrupt(Throwable exception) { if (null != callback) { callback.onInterrupt(postcard); }
@Override publicvoiddoInterceptions(final Postcard postcard, final InterceptorCallback callback) { if (null != Warehouse.interceptors && Warehouse.interceptors.size() > 0) {
checkInterceptorsInitStatus(); // 如果拦截器还没有初始化好 if (!interceptorHasInit) { callback.onInterrupt(newHandlerException("Interceptors initialization takes too much time.")); return; }
/** * Excute interceptor * * @param index current interceptor index * @param counter interceptor counter * @param postcard routeMeta */ privatestaticvoid_excute(finalint index, final CancelableCountDownLatch counter, final Postcard postcard) { if (index < Warehouse.interceptors.size()) { IInterceptoriInterceptor= Warehouse.interceptors.get(index); iInterceptor.process(postcard, newInterceptorCallback() { @Override publicvoidonContinue(Postcard postcard) { // Last interceptor excute over with no exception. counter.countDown(); // 一个拦截器执行好后,执行下一个 _excute(index + 1, counter, postcard); // When counter is down, it will be execute continue ,but index bigger than interceptors size, then U know. }
@Override publicvoidonInterrupt(Throwable exception) { // Last interceptor excute over with fatal exception.
postcard.setTag(null == exception ? newHandlerException("No message.") : exception.getMessage()); // save the exception message for backup. // 如果其中一个拦截器中断的话,就中断整个流程 counter.cancel(); // Be attention, maybe the thread in callback has been changed, // then the catch block(L207) will be invalid. // The worst is the thread changed to main thread, then the app will be crash, if you throw this exception! // if (!Looper.getMainLooper().equals(Looper.myLooper())) { // You shouldn't throw the exception if the thread is main thread. // throw new HandlerException(exception.getMessage()); // } } }); } }