ARouter源码详解

0 阅读4分钟

前言

在前面的文章 组件化 中用到了 ARouter 框架,它是专门用来做组件化改造的,官方定义如下:

一个用于帮助 Android App 进行组件化改造的框架 —— 支持模块间的路由、通信、解耦

什么是路由?可能你首先联想到的是路由器,路由器根据路由表来转发数据包,路由表决定了数据传输的路径。ARouter 就相当于一个路由器,让无依赖的双方可以通信。

下面我们就通过源码来分析 ARouter 的实现原理,本文 ARouter 源码基于:com.alibaba:arouter-api:1.5.2。

源码解析

ARouter 的简单使用在前面的文章中已有介绍,使用前需要在 Application 中用 ARouter.init(this) 来初始化 ARouter,下面我们就从这里开始分析源码:

public final class ARouter {

    private volatile static boolean hasInit = false;

    public static void init(Application application) {
        // 判断是否已经初始化
        if (!hasInit) {
            ...
            // 调用 _ARouter.init() 初始化
            hasInit = _ARouter.init(application);

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

首先判断有没有初始化,没有初始化就进行初始化,并把初始化的结果赋值给 hasInit, ARouter 的 init() 方法调用了 _ARouter 的 init() 方法:

final class _ARouter {

    private volatile static boolean hasInit = false;

    private volatile static ThreadPoolExecutor executor = DefaultPoolExecutor.getInstance();

    protected static synchronized boolean init(Application application) {
        mContext = application;
        LogisticsCenter.init(mContext, executor);
        ...
        hasInit = true;
        return true;
    }
}

_ARouter 的 init() 方法中出现了 LogisticsCenter 这个类,这个类是做什么的呢?看类名是 “物流中心”的意思 ,继续看下它的 init() 方法做了些什么:

public class LogisticsCenter {

    // 加载内存中的路由信息
    public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
        ...
        // 从插件中加载路由表
        loadRouterMap();
        if (registerByPlugin) {
            logger.info(TAG, "Load router map by arouter-auto-register plugin.");
        } else {
            Set<String> routerMap;

            // It will rebuild router map every times when debuggable.
            // 调用 ARouter.openDebug() 、第一次运行、版本更新都会更新 routerMap 。
            // PackageUtils.isNewVersion() 中通过 SharedPreference 存储的 App 的
            // versionName 和 versionCode 来判断版本是否有更新
            if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {

                // These class was generated by arouter-compiler.
                // 这里就是从 dex 中获取 com.alibaba.android.arouter.routes 包下的 .class
                // ROUTE_ROOT_PAKCAGE = "com.alibaba.android.arouter.routes";
                routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
                if (!routerMap.isEmpty()) {
                    // 把 routerMap 存入 SharedPreference
                    context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply();
                }

                // 更新 SharedPreference 中存储的 App 的版本信息
                PackageUtils.updateVersion(context); // Save new version name when router map update finishes.
            } else {
                // 直接从 SP 中拿 routerMap ,就是前面保存在 SP 中的 routerMap
                routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>()));
            }
            ...
            // 根据 className,来实例化不同的对象并调用 loadInto() 方法。
            for (String className : routerMap) {
                // 以 com.alibaba.android.arouter.routes.ARouter$$Root 开头
                if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
                    // This one of root elements, load root.
                    ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
                }
                // 以 com.alibaba.android.arouter.routes.ARouter$$Interceptors 开头
                else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
                    // Load interceptorMeta
                    ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
                }
                // 以 com.alibaba.android.arouter.routes.ARouter$$Providers 开头
                else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
                    // Load providerIndex
                    ((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
                }
            }
        }
    }

    /**
     * arouter-auto-register plugin will generate code inside this method
     * call this method to register all Routers, Interceptors and Providers
     */
    private static void loadRouterMap() {
        registerByPlugin = false;
        // auto generate register code by gradle plugin: arouter-auto-register
        // looks like below:
        // registerRouteRoot(new ARouter..Root..modulejava());
        // registerRouteRoot(new ARouter..Root..modulekotlin());
    }
}

从上面的代码可以看出,这段代码就是加载路由表的核心代码,上面有注释标出了一些代码的业务逻辑,这里再挑出几个比较难理解的地方重点讲解一下。

首先是这句代码loadRouterMap(),注释上说的是从插件中加载路由表,什么意思呢?意思是你可以选择使用ARouter提供的注册插件自动加载路由表,该注册插件会通过字节码注入的方式修改loadRouterMap(),修改完后loadRouterMap()类似下面这样:

private static void loadRouterMap() {
    registerByPlugin = false;
    register("com.alibaba.android.arouter.routes.ARouter$$Root$$XXX");
    register("com.alibaba.android.arouter.routes.ARouter$$Interceptors$$XXX");
    register("com.alibaba.android.arouter.routes.ARouter$$Providers$$XXX");
}

这种情况在编译期把路由表加载到内存中,可以缩短ARouter初始化的时间。使用该插件需要在项目的build.gradle中添加如下配置:

buildscript {
    ...
    dependencies {
        classpath "com.alibaba:arouter-register:1.0.2"
    }
}

需要注意的是,该插件必须与 1.3.0 及以上版本的 API 配合使用。

第22行从dex中获取所有com.alibaba.android.arouter.routes包下的.class文件放入routerMap,从第36行开始遍历routerMap,分成了3种情况:

  1. 如果.class文件以com.alibaba.android.arouter.routes.ARouter$$Root开头则反射创建该实例,并调用该实例的loadInto()方法,loadInto()方法传入的参数为Warehouse.groupsIndex;
  2. 如果.class文件以com.alibaba.android.arouter.routes.ARouter$$Interceptors开头则反射创建该实例,并调用该实例的loadInto()方法,loadInto()方法传入的参数为Warehouse.interceptorsIndex;
  3. 如果.class文件以com.alibaba.android.arouter.routes.ARouter$$Providers开头则反射创建该实例,并调用该实例的loadInto()方法,loadInto()方法传入的参数为Warehouse.providersIndex;

在前面的文章中,选择集成调试模式,Sync Project后,在download模块下的build\intermediates\javac\debug\classes\com\alibaba\android\arouter\routes目录下共生成了3个.class文件,这些文件是由注解处理器生成的:

ARouter$$Group$$download.class
ARouter$$Providers$$download.class
ARouter$$Root$$download.class

其中ARouter$$Root$$download.class以com.alibaba.android.arouter.routes.ARouter$$Root开头,点开ARouter$$Root$$download.class,其代码如下:

public class ARouter$$Root$$download implements IRouteRoot {
    @Override
    public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) {
        routes.put("download", ARouter$$Group$$download.class);
    }
}

其loadInto()方法将ARouter$$Group$$download.class存入routes中,routes为Map<String, Class<? extends IRouteGroup>>类型,key为download,routes就是上面的Warehouse.groupsIndex。Warehouse是存储路由信息的仓库,其代码如下:

class Warehouse {
    //用于缓存实现了IRouteGroup接口的类,key为path的第一级
    static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();
    //用于缓存路由元信息,key为path
    static Map<String, RouteMeta> routes = new HashMap<>();

    //缓存实现了IProvider接口的类的实例,key为IProvider实现类的class
    static Map<Class, IProvider> providers = new HashMap<>();
    //缓存实现了IProvider类的路由元信息,key为继承了IProvider的接口的路径
    static Map<String, RouteMeta> providersIndex = new HashMap<>();

    //缓存interceptor
    static Map<Integer, Class<? extends IInterceptor>> interceptorsIndex = new UniqueKeyTreeMap<>("More than one interceptors use same priority [%s]");
    static List<IInterceptor> interceptors = new ArrayList<>();

    static void clear() {
        routes.clear();
        groupsIndex.clear();
        providers.clear();
        providersIndex.clear();
        interceptors.clear();
        interceptorsIndex.clear();
    }
}

这样就把ARouter$$Group$$download.class存入了Warehouse.groupsIndex这个HashMap中,key为download。

接下来分析跳转的代码,跳转代码如下:

ARouter.getInstance().build(path).navigation();

跟进去:

public final class ARouter {

    private volatile static ARouter instance = null;

    private ARouter() {
    }

    public static ARouter getInstance() {
        if (!hasInit) {
            throw new InitException("ARouter::Init::Invoke init(context) first!");
        } else {
            if (instance == null) {
                synchronized (ARouter.class) {
                    if (instance == null) {
                        instance = new ARouter();
                    }
                }
            }
            return instance;
        }
    }

    public Postcard build(String path) {
        return _ARouter.getInstance().build(path);
    }

}

在getInstance()方法中先判断hasInit是否为true,如果为false抛出异常,接下来用单例模式创建ARouter实例,build()方法调用了_ARouter.getInstance().build(path):

final class _ARouter {

    private _ARouter() {
    }

    protected static _ARouter getInstance() {
        if (!hasInit) {
            throw new InitException("ARouterCore::Init::Invoke init(context) first!");
        } else {
            if (instance == null) {
                synchronized (_ARouter.class) {
                    if (instance == null) {
                        instance = new _ARouter();
                    }
                }
            }
            return instance;
        }
    }

    /**
     * Build postcard by path and default group
     */
    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
                path = pService.forString(path);
            }
            return build(path, extractGroup(path), true);
        }
    }

    //从传入的path中解析出group
    private String extractGroup(String path) {
        ...
        String defaultGroup = path.substring(1, path.indexOf("/", 1));
        if (TextUtils.isEmpty(defaultGroup)) {
            throw new HandlerException(Consts.TAG + "Extract the default group failed! There's nothing between 2 '/'!");
        } else {
            return defaultGroup;
        }
        ...
    }

    /**
     * Build postcard by path and group
     * 通过path和group拿到Postcard
     */
    protected Postcard build(String path, String group, Boolean afterReplace) {
        ...
        return new Postcard(path, group);
    }

}

第25行先判断,如果path为空抛出异常,如果想替换path,可以写一个类实现PathReplaceService接口。接着调用第33行的build()方法,这里从path中解析出group,最后新建Postcard实例,传入path和group。Postcard从名字翻译过来是明信片的意思,其承载了一次路由需要的所有信息,Postcard代码如下:

/**
 * A container that contains the roadmap.
 */
public final class Postcard extends RouteMeta {

    private Uri uri;
    private Bundle mBundle; // Data to transform

    public Postcard() {
        this(null, null);
    }

    public Postcard(String path, String group) {
        this(path, group, null, null);
    }

    public Postcard(String path, String group, Uri uri, Bundle bundle) {
        setPath(path);
        setGroup(group);
        setUri(uri);
        this.mBundle = (null == bundle ? new Bundle() : bundle);
    }


    /**
     * Navigation to the route with path in postcard.
     * No param, will be use application context.
     */
    public Object navigation() {
        return navigation(null);
    }

    /**
     * Navigation to the route with path in postcard.
     *
     * @param context Activity and so on.
     */
    public Object navigation(Context context) {
        return navigation(context, null);
    }

    /**
     * Navigation to the route with path in postcard.
     *
     * @param context Activity and so on.
     */
    public Object navigation(Context context, NavigationCallback callback) {
        return ARouter.getInstance().navigation(context, this, -1, callback);
    }
}

Postcard继承自路由元信息RouteMeta,传入path和group实际调用的是RouteMeta的setPath()方法和setGroup()方法,对RouteMeta中的path和group成员变量赋值:

/**
* It contains basic route information.
*/
public class RouteMeta {
    private RouteType type; // Type of route
    private Element rawType; // Raw type of route
    private Class<?> destination; // Destination
    private String path; // Path of route
    private String group; // Group of route

    public String getPath() {
        return path;
    }

    public RouteMeta setPath(String path) {
        this.path = path;
        return this;
    }

    public String getGroup() {
        return group;
    }

    public RouteMeta setGroup(String group) {
        this.group = group;
        return this;
    }
}

接下来看看navigation()方法做了什么?

public final class Postcard extends RouteMeta {

    public Object navigation() {
        return navigation(null);
    }

    /**
    * Navigation to the route with path in postcard.
    *
    * @param context Activity and so on.
    */
    public Object navigation(Context context) {
        return navigation(context, null);
    }

    /**
    * Navigation to the route with path in postcard.
    *
    * @param context Activity and so on.
    */
    public Object navigation(Context context, NavigationCallback callback) {
        return ARouter.getInstance().navigation(context, this, -1, callback);
    }
} 

调用了ARouter的navigation()方法并传入Postcard实例:

public final class ARouter {

    /**
    * Launch the navigation.
    */
    public Object navigation(Context mContext, Postcard postcard, int requestCode, NavigationCallback callback) {
        return _ARouter.getInstance().navigation(mContext, postcard, requestCode, callback);
    }
}

这里又调用了_ARouter的navigation()方法:

final class _ARouter {
    /**
     * Use router navigation.
     */
    protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        //若有PretreatmentService的实现,就进行预处理,可以在真正路由前进行一些判断然后中断路由。
        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 {
            //标记1,通过routeMeta完善postcard
            LogisticsCenter.completion(postcard);
        } catch (NoRouteFoundException ex) {
            logger.warning(Consts.TAG, ex.getMessage());

            //没有找到路由的回调
            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() {
                /**
                 * 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 {
            //标记2,绿色通道,不走拦截器,获取路由结果
            return _navigation(postcard, requestCode, callback);
        }

        return null;
    }
}

我们先看看标记1处代码做了什么:

public class LogisticsCenter {

    /**
     * Completion the postcard by route metas
     *
     * @param postcard Incomplete postcard, should complete by this method.
     */
    public synchronized static void completion(Postcard postcard) {
        //通过path去Warehouse.routes中拿RouteMeta
        RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
        //如果RouteMeta为空
        if (null == routeMeta) {
            // Maybe its does't exist, or didn't load.
            //如果Warehouse.groupsIndex中没有这个group,抛出异常
            if (!Warehouse.groupsIndex.containsKey(postcard.getGroup())) {
                throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");
            } else {
                // Load route and cache it into memory, then delete from metas.
                //重新调用group的loadInto()方法
                addRouteGroupDynamic(postcard.getGroup(), null);

                //重新执行completion()方法
                completion(postcard); // Reload
            }
        } else {
            //把routeMeta里面的配置传递给postcard
            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 auto inject.
                    postcard.getExtras().putStringArray(ARouter.AUTO_INJECT, paramsType.keySet().toArray(new String[]{}));
                }

                // Save raw uri
                postcard.withString(ARouter.RAW_URI, rawUri.toString());
            }

            switch (routeMeta.getType()) {
                //如果类型是PROVIDER
                case PROVIDER: // if the route is provider, should find its instance
                    // Its provider, so it must implement IProvider
                    Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
                    //去Warehouse.providers中获取实例
                    IProvider instance = Warehouse.providers.get(providerMeta);
                    //如果instance为null
                    if (null == instance) { // There's no instance of this provider
                        IProvider provider;
                        try {
                            //反射创建实例
                            provider = providerMeta.getConstructor().newInstance();
                            provider.init(mContext);
                            //存入Warehouse.providers
                            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);
                    // 设置greenChannel为true,跳过所有的拦截器
                    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)) {
            // If this group is included, but it has not been loaded
            // load this group first, because dynamic route has high priority.
            //调用实例的loadInto()方法添加到Warehouse.routes 
            Warehouse.groupsIndex.get(groupName).getConstructor().newInstance().loadInto(Warehouse.routes);
            //从Warehouse.groupsIndex中移除key为groupName的数据
            Warehouse.groupsIndex.remove(groupName);
        }

        // cover old group.
        if (null != group) {
            group.loadInto(Warehouse.routes);
        }
    }
}

上面的completion()方法先去Warehouse.routes中拿RouteMeta,Warehouse就是前面存储路由信息的仓库,Warehouse.routes是其中缓存路由元信息的HashMap。判断如果RouteMeta为null,调用addRouteGroupDynamic()方法,去Warehouse.groupsIndex中取出缓存的类,使用反射创建该类的实例,然后调用其loadInto()方法,这样就调用了ARouter$$Group$$download.class的loadInto()方法,其代码如下:

public class ARouter$$Group$$download implements IRouteGroup {
    @Override
    public void loadInto(Map<String, RouteMeta> atlas) {
        atlas.put("/download/DownloadActivity", RouteMeta.build(RouteType.ACTIVITY, DownloadActivity.class, "/download/downloadactivity", "download", null, -1, -2147483648));
        atlas.put("/download/service", RouteMeta.build(RouteType.PROVIDER, DownloadServiceImpl.class, "/download/service", "download", null, -1, -2147483648));
    }
}

其loadInto()方法把RouteMeta通过build()方法创建的实例添加到Warehouse.routes中。

回到前面的代码,接着又调用了一次completion()方法,此时routeMeta不再为null,将routeMeta的配置信息(destination、type等信息)传递给postcard,如果routeMeta类型是PROVIDER,会反射创建实例并存入Warehouse.providers。然后判断是否是绿色通道,如果不是绿色通道,需要执行拦截器。如果是绿色通道会执行标记2处的代码开始准备跳转,标记2处代码如下:

private Object _navigation(final Postcard postcard, final int requestCode, final NavigationCallback callback) {
    final Context currentContext = postcard.getContext();

    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 (0 != flags) {
                intent.setFlags(flags);
            }

            // Non activity, need FLAG_ACTIVITY_NEW_TASK
            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() {
                    startActivity(requestCode, currentContext, intent, postcard, callback);
                }
            });

            break;
        case PROVIDER:
            return postcard.getProvider();
        case BOARDCAST:
        case CONTENT_PROVIDER:
        case FRAGMENT:
            //Broadcast、ContentProvider、Fragment,都是使用postcard.getDestination()反射创建实例
            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;
}

在这里先判断postcard的RouteType,RouteType是一个枚举:

public enum RouteType {
    ACTIVITY(0, "android.app.Activity"),
    SERVICE(1, "android.app.Service"),
    PROVIDER(2, "com.alibaba.android.arouter.facade.template.IProvider"),
    CONTENT_PROVIDER(-1, "android.app.ContentProvider"),
    BOARDCAST(-1, ""),
    METHOD(-1, ""),
    FRAGMENT(-1, "android.app.Fragment"),
    UNKNOWN(-1, "Unknown route type");
    ...
}    

如果是Activity,就把postcard里面的参数传递给Intent,最终调用startActivity()方法进行跳转;如果是Provider,直接通过postcard.getProvider()拿到IProvier的实现类的单例;Broadcast、ContentProvider、Fragment都是使用postcard.getDestination()反射创建实例并返回。

参考资料: juejin.cn/post/720004…