路由框架ARouter的使用与原理分析

Arouter简介

 ARouter是阿里开源的一款路由框架,为组件化提供解决方案,它支持解析标准URL进行跳转,并自动注入参数到目标页面中;支持添加多个拦截器,自定义拦截顺序。
所谓组件化就是将APP按照一定的功能和业务拆分成多个小组件,不同的组件由不同的开发小组来负责,这样就可以解决大型APP开发过程中的开发与协作的问题,将这些问题分散到小的APP中。

(1)原生路由方案:使用显示Intent和隐式Intent跳转

  • 显示Intent存在直接依赖,耦合度过高;
  • 隐式Intent存在规则集中式管理Path,导致协作困难;
  • 原生路由跳转一旦调用startActivity,后面的流程将无法进行控制拦截;

(2)ARouter自定义路由方案:使用解析标准URL跳转

  • 通过解析URL索引进行跳转,解决依赖的问题;
  • 通过分布式管理页面配置,解决隐式Intent中集中式管理Path的问题;
  • 通过AOP方式支持添加多个拦截器并自定义拦截顺序,解决跳转过程中无法控制的问题;
  • 整个路由跳转过程透明,拥有更好的扩展性;

2. ARouter基本使用

ARouter Github地址: https://github.com/alibaba/ARouter

(1)配置app的build.gradle;

android {
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
            }
        }
    }
}

dependencies {
    // Replace with the latest version
    implementation 'com.alibaba:arouter-api:1.5.1'
    annotationProcessor 'com.alibaba:arouter-compiler:1.5.1' // 注解处理器
    ...
}

 如果使用Kotlin开发,将上述配置改为:

// 添加'kotlin-kapt'插件
apply plugin: 'kotlin-kapt'

android {
    kapt {
          arguments {
               arg("AROUTER_MODULE_NAME", project.getName())
          }
    }
}

dependencies {
    implementation 'com.alibaba:arouter-api:1.5.1'
    kapt 'com.alibaba:arouter-compiler:1.5.1' // 注解处理器
    ...
}

(2)初始化SDK,释放ARouter资源?;

public WanFlutterApplication extends Application {

    private boolean isDebug = true;

    @Override
    public void onCreate() {
        if (isDebug) {           // 在init方法之前调用,否则不起作用
            ARouter.openLog();     // 打印日志
            ARouter.openDebug();   // InstantRun mode需开启调试模式,但是线上需将其关闭
        }
        ARouter.init(this);
    }
}

(3)使用@Router注解定义一个路由页面;


// Router path至少需要两级
// "/xx/xxx"

@Router("/app/HomeActivity")
public HomeActivity extends AppcompactActivity {

    // 如果name与属性名称一致
    // 可以不指定@Autowired注解的name值
    @Autowired
    Int id;

    @Autowired(name="key2")
    String userName;

    @Autowired(name="test")
    Test test;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // ARouter inject注入
        // 注意:如果没有参数传递,这句可以不写
        // 注意:需要在Application中调用ARouter.getInstance.destory()释放资源
        ARouter.getInstance().inject(this);
    }
}

(4)Activity/Fragment路由跳转,传参数,获取返回值;

// a. 不传递参数跳转
ARouter.getInstance().build("/app/HomeActivity").navigation();

// b. 使用URL跳转
// 我们可以在清单文件中配置<data></data>标签指定uri的值
// <intent-filter>
//     <data
//        android:host="m.aliyun.com"
//        android:scheme="arouter"/>
//      ...
// </intent-filter>
Uri uri = getIntent().getData();
ARouter.getInstance().build(uri).navigation();

// c. 传递参数跳转
// 支持基本数据类型、Bundle、数组、列表、Serializable、Parcelable
// 跳转目标页面使用@Autowired注解获取
ARouter.getInstance().build("/app/HomeActivity")
            .withInt("id", 88888)
            .withString("name", "jiangdg")
            .withObject("test", new Test("Jack", "Rose"))
            .navigation();

// d. 跳转动画
ARouter.getInstance().build("/app/HomeActivity")
                     .withTransition(R.anim.in, R.anim.out)
                     .navigation();

// e. Fragment跳转
Fragment fragment = (Fragment)ARouter.getInstance().build("/app/TestFragment").navigation()

// f. 获取返回值
int requestCode = 1;
ARouter.getInstance().build("/app/HomeActivity").navigation(context, requestCode);

(5)ARouter拦截器实现

  • a. 使用@Interceptor注解定义拦截器,并实现IInterceptor接口实现;

// priority值表示拦截器优先级,越小优先级越大;
// name值表示拦截器的名称;

@Interceptor(priority=1, name="test")
public class UseIIterceptor implements IInterceptor {

    @Override
    public void init(Context context) {
        // 拦截器初始化
    }

    @Override
    public void process(Postcard postCard, InterceptorCallback callback) {
        // 拦截器处理逻辑
        // ...
        // 如:当跳转到"/app/HomeActivity"页面时,作相关的处理
        if (postCard.getPath().equal("/app/HomeActivity")) {
            Log.d(TAG, "I Get it");
        }
    }
}
  • b. 使拦截器生效,通过注册路由监听器实现;
ARouter.getInstance().build("/app/HomeActivity")
                     .navigation(context, new NavigationCallback() {
                        @Override
                        public void onFound(Postcard postcard) {
                            // 路由目标被发现时调用
                        }

                        @Override
                        public void onArrival(Postcard postcard) {
                            // 路由达到之后调用
                        }

                        @Override
                        public void onLost(Postcard postcard) {
                            // 路由被丢失时调用
                        }

                        @Override
                        public void onInterrupt(Postcard postcard) {
                            // 路由被拦截时调用
                        }
                     });

Postcard是一个包含路线图(roadmap)的容器,它允许让我们获取路径的组(group)以及全路径等信息。
 拦截器最终执行顺序: init->onFound->process->onLost(丢失)/onInterrupt(拦截)/onArrival(到达)

(6)自定义分组

 ARouter使用分组管理路由的跳转,防止应用在运行时一次性加载所有路由信息造成资源浪费。

// 目的路由新增group值
@Router(path = "/app/HomeActivity", group="home")
public HomeActivity extends AppcompactActivity {

}

// 跳转指定group
ARouter.getInstance().build("/app/HomeActivity", "home").navigation();

(7)支持服务管理,通过依赖注入的方式实现不同组件之间解耦;

 ARouter提供了Service management功能,支持不同组件(模块)交互进一步解耦,即其他组件只要获取目标组件(模块)的Service实例,
就可以通过它调用该组件暴露出来的接口,这个功能通常被用在组件化各个组件之间的通信。

  • 首先,定义一个继承于IProvider的接口Service,它用于像外界暴露组件提供服务的接口;
// 定义接口
public interface UserSerive extends IProvider {
    UserInfo getUserInfo();
    // 前往完善个人信息页面
    void toFillUserProfileActivity(Context context);
    // 前往登录页面
    void toLoginActivity(Context context);
}

// 实现接口
@Route(path="/service/user", name = "UserService")
public class UserServiceImpl implements UserService {

    @Override
    UserInfo getUserInfo() {
        return UserInfo("jiangdg", 18, "male");
    }

    @Override
    void toFillUserProfileActivity(Context context) {
        // 注:这里也可以使用ARouter进行跳转
        Intent intent = new Intent(context, FillUserProfileActivity.class);
        context.startActivity(intent);
    }

    @Override
    void toLoginActivity(Context context) {
        // 注:这里也可以使用ARouter进行跳转
        Intent intent = new Intent(context, LoginActivity.class);
        context.startActivity(intent);
    }
}

// 其次,外界组件(模块)获取目标组件暴露的Service实例;

// 方式一:使用依赖注入或注解获取
@Autowired
UserService userService;
@Autowired(name = "/service/user")
UserService userSerivce;

// 方式二:使用依赖关系查找
UserService userSerivce = ARouter.getInstance().navigation(UserSerive.class);
UserService userSerivce = (UserService)ARouter.getInstance().build("/service/user").navigation();

 注意:ARouter还提供了降低策略和预处理,分别是DegradeServicePretreatmentService


 ARouter的工作原理为在编译阶段根据注解解释器对路由注解,拦截器注解以及自动装配注解注解进行解释并生成辅助代码,待运行期与API接口一起提供给宿主APP使用。此外,ARouter框架使用了外观模式进行封装,隐藏了具体的实现细节,提供了一个统一的入口供外界使用。

1. ARouter初始化过程分析

 ARouter初始化过程主要是获取注解处理器生成的辅助类存储的路由信息,并将其加载到内存中的过程
ARouter初始化入口为ARouter.init(),它最终会调用LogisticsCenter.init()方法完成初始化工作。

具体源码如下:

// 线程池
// 核心线程大小:CPU_COUNT + 1
// 最大线程数量:CPU_COUNT + 1
// 阻塞队列大小:64
private volatile static ThreadPoolExecutor executor = DefaultPoolExecutor.getInstance();

protected static synchronized boolean init(Application application) {
    mContext = application;
    // 外观模式
    // 执行实际的ARouter初始化逻辑,参数为上下文和线程池对象
    LogisticsCenter.init(mContext, executor);
    logger.info(Consts.TAG, "ARouter init success!");
    hasInit = true;
    // 主线程Handler
    mHandler = new Handler(Looper.getMainLooper());

    return true;
}

 LogisticsCenter.init()的初始化过程,分为两步:

  • 首先,获取编译器生成的所有类的classname,它们位于包"com.alibaba.android.arouter.routes"下;
  • 其次,根据classname得到注解处理器生成的路由信息并缓存到内存中,即Warehouse对应的字段中;

具体源码如下:

public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
    mContext = context;
    executor = tpe;

    try {
            ...
            Set<String> routerMap;
            if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
                logger.info(TAG, "Run with debug mode or new install, rebuild router map.");
                // These class was generated by arouter-compiler.
                // 1. 加载注解处理器生成的路由信息,包名为"com.alibaba.android.arouter.routes"
                // 缓存到内存中WareHouse
                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 finishes.
            } 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>()));
            }

            // 2. 加载注解处理器生成的路由信息,缓存到内存中WareHouse
            // 如 ARouter$$Root$$模块名称
            //    ARouter$$Providers$$模块名称
            //    ARouter$$Interceptors$$模块名称
            for (String className : routerMap) {
                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);
                } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
                    // Load interceptorMeta
                    ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
                } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
                    // Load providerIndex
                    ((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
                }
            }
        }
        ...
    } catch (Exception e) {
        throw new HandlerException(TAG + "ARouter init logistics center exception! [" + e.getMessage() + "]");
    }
}
  • Warehouse

Warehouse相当于ARouter框架的“数据仓库”,它将被用于缓存编译处理器生成的路由信息(RouteMeta)。

class Warehouse {
    /**
     * groupsIndex缓存路列表
     *
     * key 路由分组;value 注解处理器自动生成的路由组,如ARouter$$Group$$service(service分组)
     */
    static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();

    /**
     * routes 缓存所有路由的元数据(不区分Group)
     *
     * key 路由路径;value 路由元数据,如RouteMeta.build(RouteType.ACTIVITY, ....)
     */
    static Map<String, RouteMeta> routes = new HashMap<>();

    /**
     * 缓存provider(服务)列表
     *
     * key 服务class;value 注解处理器自动生成的服务组,如ARouter$$Providers$$camera(service分组)
     */
    static Map<Class, IProvider> providers = new HashMap<>();
    static Map<String, RouteMeta> providersIndex = new HashMap<>();

    /**
     * 缓存拦截器列表
     *
     * key 拦截器优先级;value 注解处理器自动生成拦截器,如ARouter$$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();
    }
}
  • RouteMeta

RouteMeta表示路由元数据,它存储了路由的类型、路径、分组、优先级等信息。

public class RouteMeta {
    private RouteType type;         // 路由类型,如ACTIVITY、SERVICE、FRAGMENT、PROVIDER等
    private Element rawType;        // 路由的原始类型,如ElementKind.CLASS表示是一个类
    private Class<?> destination;   // 被@Route注解的class对象
    private String path;            // 路由路径
    private String group;           // 路由分组名称
    private int priority = -1;      // 优先级,数字越小优先级越高
    private int extra;              // 额外数据
    private Map<String, Integer> paramsType;  // 参数类型
    private String name;

    private Map<String, Autowired> injectConfig; // 自定装配参数集合
    ...
}

2. ARouter路由跳转过程分析

 ARouter路由跳转过程主要是借助了Postcard类来封装执行路由跳转所需的数据,并调用其navigation()方法执行跳转。
Postcard的创建过程如下,具体源码为:

// ARouter#build()方法
public Postcard build(String path) {
    return _ARouter.getInstance().build(path);
}

// _ARouter#build()方法
protected Postcard build(String path) {
    if (TextUtils.isEmpty(path)) {
        throw new HandlerException(Consts.TAG + "Parameter is invalid!");
    } else {
        // 1. 获取PathReplaceService,如果用户有重写PathReplaceService
        // 否则为null。注:PathReplaceService即替换路由路径
        PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
        if (null != pService) {
            path = pService.forString(path);
        }
        // 2. 创建路由图Postcard
        // 获取默认group,即如果没有指定group,则将/xx/xxx,xx则为默认group
        return build(path, extractGroup(path), true);
    }
}

// _ARouter#build()方法
protected Postcard build(String path, String group, Boolean afterReplace) {
    if (TextUtils.isEmpty(path) || TextUtils.isEmpty(group)) {
        throw new HandlerException(Consts.TAG + "Parameter is invalid!");
    } else {
        if (!afterReplace) {
            PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
            if (null != pService) {
                path = pService.forString(path);
            }
        }
        // 实例化一个Postcard对象
        // 将路由路由和分组信息保存
        return new Postcard(path, group);
    }
}

 接下来,我们分析下通过Postcard是如何完成最后的跳转逻辑的。通过分析Postcard#navigation()可知,它又继续调用了
_ARouter的navigation()方法,在该方法中执行具体的操作。源码如下所示:

protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
    // 1. 获取pretreatmentService(预处理)服务对象
    // 如果用户实现了的话,返回false说明用户取消了跳转
    PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
    if (null != pretreatmentService && !pretreatmentService.onPretreatment(context, postcard)) {
        return null;
    }

    // 2. 设置context到Postcard
    postcard.setContext(null == context ? mContext : context);

    // 3. 完善对Postcard数据的填充
    // 如果没有发现对应的路由信息,报“There's no route matched!”异常
    // 并回调NavigationCallback的onLost方法(如果有的话)或者降级处理
    try {
        LogisticsCenter.completion(postcard);
    } catch (NoRouteFoundException ex) {
        // 回调callback的onLost或者DegradeService的onLost
        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;
    }

    // 4. 路由信息匹配成功,触发onFound回调
    if (null != callback) {
        callback.onFound(postcard);
    }
    // 5. 根据greenChannel标志,执行拦截器(拦截器代码需异步执行,防止ANR)
    //  默认为false,但如果routeType是Provider或Fragment,会将其置为true(Logistics.completion)
    //  因此拦截器只针对Activity,进入InterceptorServiceImpl.doInterceptions
    if (!postcard.isGreenChannel()) {
        interceptorService.doInterceptions(postcard, new InterceptorCallback() {
            // 继续执行跳转逻辑
            // 即根据路由的类型,执行最终的跳转,intent...
            @Override
            public void onContinue(Postcard postcard) {
                _navigation(postcard, requestCode, callback);
            }

            // 跳转被拦截
            @Override
            public void onInterrupt(Throwable exception) {
                // 回调NavigationCallback的onInterrupt方法
                if (null != callback) {
                    callback.onInterrupt(postcard);
                }
            }
        });
    } else {
        return _navigation(postcard, requestCode, callback);
    }

    return null;
}

 _ARouter#navigation主要做了以下几件事情:

(1)判断用户是否实现了PretreatmentService,如果返回false,说明用户取消了接下来的跳转;
(2)将WareHouse缓存的路由信息填充到PostCard中,通过调用LogisticsCenter.completion()实现;
(3)判断路由类型,如果是Activity,进入拦截器处理逻辑(线程池),并决定拦截还是继续执行;
(4)否则,继续执行真正的跳转或其他操作。

 下面我们重点分析下(2)、(3)阶段:

  • LogisticsCenter.completion()

  该方法的作用就是读取WareHouse缓存的路由信息填充到PostCard中。

//
public synchronized static void completion(Postcard postcard) {
    if (null == postcard) {
        throw new NoRouteFoundException(TAG + "No postcard!");
    }
    // 3-1 通过路由path获取路由的元数据RouteMeta
    // (1)如果获取元数据失败,则
    //      如果没有找到(路由分组,如ARouter$$Group$$service,不存在),抛出NoRouteFoundException
    //      否则,尝试动态加载Group,然后再尝试completion
    RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
    if (null == routeMeta) {
        // Maybe its does't exist, or didn't load.
        if (!Warehouse.groupsIndex.containsKey(postcard.getGroup())) {
            throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");
        } else {
            try {
                if (ARouter.debuggable()) {
                    logger.debug(TAG, String.format(Locale.getDefault(), "The group [%s] starts loading, trigger by [%s]", postcard.getGroup(), postcard.getPath()));
                }
                // 动态加载group
                //         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.
                //            Warehouse.groupsIndex.get(groupName).getConstructor().newInstance().loadInto(Warehouse.routes);
                //            Warehouse.groupsIndex.remove(groupName);
                //        }
                addRouteGroupDynamic(postcard.getGroup(), null);
            } catch (Exception e) {
                throw new HandlerException(TAG + "Fatal exception when loading group meta. [" + e.getMessage() + "]");
            }

            completion(postcard);   // Reload
        }
    }
    // (2)获取路由元数据routeMeta成功,将routeMeta的数据依次填充的Postcard相关字段
    else {
        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)) {
                // 获取所有传递参数,保存到Bundle
                // 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());
        }
        // b. 根据路由类型决定是否屏蔽拦截器
        // 如果是Provider,通过反射实例化一个对象保存到PostCard中,然后将greenChannel标志置为true
        // 如果是Fragment,将greenChannel标志置为true
        // ps:_ARouter.navigation方法最终根据greenChannel决定是否执行拦截器
        switch (routeMeta.getType()) {
            case PROVIDER:
                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) {
                        logger.error(TAG, "Init provider failed!", e);
                        throw new HandlerException("Init provider failed!");
                    }
                }
                postcard.setProvider(instance);
                postcard.greenChannel();    // Provider should skip all of interceptors
                break;
            case FRAGMENT:
                postcard.greenChannel();    // Fragment needn't interceptors
            default:
                break;
        }
    }
}
  • ARouter#_navigation()

 该方法将根据路由类型,执行实际上的跳转。

(1)如果是Activity,调用startActivity跳转,参数从PostCard中获取;
(2)如果是IProvider(服务),直接返回IProvicer对象;
(3)如果是Broadcast、ContentProvider、Fragment,通过反射实例化一个对象并返回;

 具体源码如下:

private Object _navigation(final Postcard postcard, final int requestCode, final NavigationCallback callback) {
    // 1 获取上下文
    final Context currentContext = postcard.getContext();
    // 2 根据路由类型,执行实际上的跳转
    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有可能处于线程池中(拦截器是在线程池中执行)
            runInMainThread(new Runnable() {
                @Override
                public void run() {
                    startActivity(requestCode, currentContext, intent, postcard, callback);
                }
            });

            break;
        case PROVIDER:
            // 返回IProvider对象
            return postcard.getProvider();
        case BOARDCAST:
        case CONTENT_PROVIDER:
        case FRAGMENT:
            // 返回Broadcast、Content Provider、Fragment对象
            // 如果是Fragment, 还需要setArguments,即设置传递参数
            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;
}
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:白松林 返回首页