Android开发经验谈Android开发Android开发随笔

深入解析阿里巴巴ARouter路由

2020-05-21  本文已影响0人  程序媛饭冰冰

目录介绍

好消息

注解学习小案例

01.原生跳转实现

02.实现组件跳转方式

2.1 传统跳转方式

2.2 为何需要路由

03.ARouter配置与优势

3.1 ARouter的优势

3.2 至于配置和使用

04.跨进程组件通信

4.1 URLScheme【例如:ActivityRouter、ARouter等】

4.2 AIDL

4.3 BroadcastReceiver

4.4 路由通信注意要点

05.ARouter的结构

06.ARouter的工作流程

6.1 初始化流程

 */
public static void init(Application application) {
    //如果没有初始化,则
    if (!hasInit) {
        logger = _ARouter.logger;
        _ARouter.logger.info(Consts.TAG, "ARouter init start.");

        //做初始化工作
        hasInit = _ARouter.init(application);

        if (hasInit) {
            _ARouter.afterInit();
        }

        _ARouter.logger.info(Consts.TAG, "ARouter init over.");
    }
}

*   之后接着看_ARouter.init(application)这行代码,点击去查看

    ```
    protected static synchronized boolean init(Application application) {
        //赋值上下文
        mContext = application;
        //初始化LogisticsCenter
        LogisticsCenter.init(mContext, executor);
        logger.info(Consts.TAG, "ARouter init success!");
        hasInit = true;
        mHandler = new Handler(Looper.getMainLooper());
        return true;
    }
    ```

*   接下来看看LogisticsCenter里面做了什么

    ```
    public class LogisticsCenter {
        /**
    ```

 */
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
    mContext = context;
    executor = tpe;
    try {
        long startInit = System.currentTimeMillis();
        Set<String> routerMap;
        //debug或者版本更新的时候每次都重新加载router信息
        // It will rebuild router map every times when debuggable.
        if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
            logger.info(TAG, "Run with debug mode or new install, rebuild router map.");
            // These class was generate by arouter-compiler.
            //加载alibaba.android.arouter.routes包下载的类
            routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
            if (!routerMap.isEmpty()) {
                context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply();
            }
            PackageUtils.updateVersion(context);    // Save new version name when router map update finish.
        } else {
            logger.info(TAG, "Load router map from cache.");
            routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>()));
        }

        logger.info(TAG, "Find router map finished, map size = " + routerMap.size() + ", cost " + (System.currentTimeMillis() - startInit) + " ms.");
        startInit = System.currentTimeMillis();

        for (String className : routerMap) {
            if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
                // This one of root elements, load root. 
                //导入ARouter$$Root$$app.java,初始化Warehouse.groupsIndex集合
                ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
            } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
                // Load interceptorMeta
                //导入ARouter$$Interceptors$$app.java,初始化Warehouse.interceptorsIndex集合
                ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
            } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
                // Load providerIndex
                //导入ARouter$$Providers$$app.java,初始化Warehouse.providersIndex集合
                ((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
            }
        }

        /*******部分代码省略********/
    } catch (Exception e) {
        throw new HandlerException(TAG + "ARouter init logistics center exception! [" + e.getMessage() + "]");
    }
}

6.2 跳转页面流程

07.ARouter调用api

7.1 最简单调用

7.2 build源码分析

 */
protected Postcard build(String path) {
    if (TextUtils.isEmpty(path)) {
        throw new HandlerException(Consts.TAG + "Parameter is invalid!");
    } else {
        PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
        if (null != pService) {
            path = pService.forString(path);
        }
        return build(path, extractGroup(path));
    }
}

#### 7.3 navigation分析

*   如下所示

    ```
    final class _ARouter {
        protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
            try {
                LogisticsCenter.completion(postcard);
            } catch (NoRouteFoundException ex) {
                /**************部分代码省略***************/
                if (null != callback) {
                    callback.onLost(postcard);
                } else {    // No callback for this invoke, then we use the global degrade service.
                    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() {
                    @Override
                    public void onContinue(Postcard postcard) {
                        _navigation(context, postcard, requestCode, callback);
                    }
                    @Override
                    public void onInterrupt(Throwable exception) {
                        //中断处理
                        if (null != callback) {
                            callback.onInterrupt(postcard);
                        }
                    }
                });
            } else {
                return _navigation(context, postcard, requestCode, callback);
            }

            return null;
        }

        private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
            //没有上下文环境,就用Application的上下文环境
            final Context currentContext = null == context ? mContext : context;
            switch (postcard.getType()) {
                case ACTIVITY:
                    // Build intent 构建跳转的intent
                    final Intent intent = new Intent(currentContext, postcard.getDestination());
                    intent.putExtras(postcard.getExtras());
                    // Set flags. 设置flag
                    int flags = postcard.getFlags();
                    if (-1 != flags) {
                        intent.setFlags(flags);
                    } else if (!(currentContext instanceof Activity)) {    // Non activity, need less one flag.
                        //如果上下文不是Activity,则添加FLAG_ACTIVITY_NEW_TASK的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;
        }
    }
    ```

### 08.Postcard信息携带

*   Postcard主要为信息的携带者,内容是在构造一次路由信息的时候生产的,其继承于RouteMeta。RouteMeta是在代码编译时生成的内容,主要在初始化WareHouse时对跳转信息做了缓存。
*   看看代码如下所示
```
//Postcard继承于RouteMeta
public final class Postcard extends RouteMeta

//然后看看编译生成的文件
/**
```
public class ARouter$$Group$$me implements IRouteGroup {
  @Override
  public void loadInto(Map<String, RouteMeta> atlas) {
    atlas.put("/me/ExperienceCouponActivity", RouteMeta.build(RouteType.ACTIVITY, ExperienceCouponActivity.class, "/me/experiencecouponactivity", "me", null, -1, -2147483648));
    atlas.put("/me/ServiceActivity", RouteMeta.build(RouteType.ACTIVITY, ServiceActivity.class, "/me/serviceactivity", "me", null, -1, -2147483648));
    atlas.put("/me/SettingActivity", RouteMeta.build(RouteType.ACTIVITY, SettingActivity.class, "/me/settingactivity", "me", null, -1, -2147483648));
    atlas.put("/me/UdeskServiceActivity", RouteMeta.build(RouteType.ACTIVITY, UdeskServiceActivity.class, "/me/udeskserviceactivity", "me", null, -1, -2147483648));
  }
}

### 10.DegradeService降级容错服务

*   首先,自定义一个类,需要继承DegradeService类,如下所示

    ```
    /**
     * <pre>
     *     @author 杨充
     *     blog  : https://github.com/yangchong211
     *     time  : 2018/08/24
     *     desc  : ARouter路由降级处理
     *     revise:
    ```

*/
@Route(path = DegradeServiceImpl.PATH)
public class DegradeServiceImpl implements DegradeService {

static final String PATH = "/service/DegradeServiceImpl";

@Override
public void onLost(Context context, Postcard postcard) {
    if (context != null && postcard.getGroup().equals("activity")) {
        Intent intent = new Intent(context, WebViewActivity.class);
        intent.putExtra(Constant.URL, Constant.GITHUB);
        intent.putExtra(Constant.TITLE, "github地址");
        ActivityCompat.startActivity(context, intent, null);
    }
}

@Override
public void init(Context context) {

}

}

11.Interceptor拦截器

                 *
                 * @param postcard route meta
                 */
                @Override
                public void onContinue(Postcard postcard) {
                    _navigation(context, 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(context, postcard, requestCode, callback);
        }
        return null;
    }
}

*   拦截器的初始化

    *   在刚开始初始化的时候,就已经做了这个操作。

    ```
    final class _ARouter {
        static void afterInit() {
            // Trigger interceptor init, use byName.
            interceptorService = (InterceptorService) ARouter.getInstance().build("/arouter/service/interceptor").navigation();
        }
    }
    ```

*   InterceptorServiceImpl的init方法:

    ```
    @Route(path = "/arouter/service/interceptor")
    public class InterceptorServiceImpl implements InterceptorService {
        @Override
        public void init(final Context context) {
            LogisticsCenter.executor.execute(new Runnable() {
                @Override
                public void run() {
                    if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) {
                        //循环遍历仓库中的拦截器
                        for (Map.Entry<Integer, Class<? extends IInterceptor>> entry : Warehouse.interceptorsIndex.entrySet()) {
                            Class<? extends IInterceptor> interceptorClass = entry.getValue();
                            try {
                                //反射机制构造自定义的每一个拦截器实例
                                IInterceptor iInterceptor = interceptorClass.getConstructor().newInstance();
                                iInterceptor.init(context);
                                //并将其添加在缓存中
                                Warehouse.interceptors.add(iInterceptor);
                            } catch (Exception ex) {
                                throw new HandlerException(TAG + "ARouter init interceptor error! name = [" + interceptorClass.getName() + "], reason = [" + ex.getMessage() + "]");
                            }
                        }
                        interceptorHasInit = true;
                        logger.info(TAG, "ARouter interceptors init over.");
                        synchronized (interceptorInitLock) {
                            interceptorInitLock.notifyAll();
                        }
                    }
                }
            });
        }
    }
    ```

*   拦截器的工作过程

    ```
    @Route(path = "/arouter/service/interceptor")
    public class InterceptorServiceImpl implements InterceptorService {
        @Override
        public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) {
            if (null != Warehouse.interceptors && Warehouse.interceptors.size() > 0) {
                //检测是否初始化完所有的烂机器
                checkInterceptorsInitStatus();
                //没有完成正常的初始化,抛异常
                if (!interceptorHasInit) {
                    callback.onInterrupt(new HandlerException("Interceptors initialization takes too much time."));
                    return;
                }
                //顺序遍历每一个拦截器,
                LogisticsCenter.executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size());
                        try {
                            _excute(0, interceptorCounter, postcard);
                            interceptorCounter.await(postcard.getTimeout(), TimeUnit.SECONDS);
                            //拦截器的遍历终止之后,如果有还有没有遍历的拦截器,则表示路由事件被拦截
                            if (interceptorCounter.getCount() > 0) {    // Cancel the navigation this time, if it hasn't return anythings.
                                callback.onInterrupt(new HandlerException("The interceptor processing timed out."));
                            } else if (null != postcard.getTag()) {    // Maybe some exception in the tag.
                                callback.onInterrupt(new HandlerException(postcard.getTag().toString()));
                            } else {
                                callback.onContinue(postcard);
                            }
                        } catch (Exception e) {
                            callback.onInterrupt(e);
                        }
                    }
                });
            } else {
                callback.onContinue(postcard);
            }
        }

        //执行拦截器的过滤事件
        private static void _excute(final int index, final CancelableCountDownLatch counter, final Postcard postcard) {
            if (index < Warehouse.interceptors.size()) {
                IInterceptor iInterceptor = Warehouse.interceptors.get(index);
                iInterceptor.process(postcard, new InterceptorCallback() {
                    @Override
                    public void onContinue(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
                    public void onInterrupt(Throwable exception) {
                        // Last interceptor excute over with fatal exception.
                        postcard.setTag(null == exception ? new HandlerException("No message.") : exception.getMessage());    // save the exception message for backup.
                        counter.cancel();
                    }
                });
            }
        }
    }
    ```

### 12.数据传输和自动注入

### 13.多dex的支持

*   可查看multidex源码:

    ```
    public class ClassUtils {  
      /**
         * Identifies if the current VM has a native support for multidex, meaning there is no need for
    ```

 *
 * @return true if the VM handles multidex
 */
private static boolean isVMMultidexCapable() {
    boolean isMultidexCapable = false;
    String vmName = null;

    try {
        if (isYunOS()) {    // YunOS需要特殊判断
            vmName = "'YunOS'";
            isMultidexCapable = Integer.valueOf(System.getProperty("ro.build.version.sdk")) >= 21;
        } else {    // 非YunOS原生Android
            vmName = "'Android'";
            String versionString = System.getProperty("java.vm.version");
            if (versionString != null) {
                Matcher matcher = Pattern.compile("(\\d+)\\.(\\d+)(\\.\\d+)?").matcher(versionString);
                if (matcher.matches()) {
                    try {
                        int major = Integer.parseInt(matcher.group(1));
                        int minor = Integer.parseInt(matcher.group(2));
                        isMultidexCapable = (major > VM_WITH_MULTIDEX_VERSION_MAJOR)
                                || ((major == VM_WITH_MULTIDEX_VERSION_MAJOR)
                                && (minor >= VM_WITH_MULTIDEX_VERSION_MINOR));
                    } catch (NumberFormatException ignore) {
                        // let isMultidexCapable be false
                    }
                }
            }
        }
    } catch (Exception ignore) {

    }

    Log.i(Consts.TAG, "VM with name " + vmName + (isMultidexCapable ? " has multidex support" : " does not have multidex support"));
    return isMultidexCapable;
}

}


14.InstantRun支持

15.生成的编译代码

上一篇 下一篇

猜你喜欢

热点阅读