ActivityRouter源码解析

Header

在如今的 Android 组件化开发中,一款好的路由框架是不可或缺的。比如目前阿里的 ARouter 、美团的 WMRouter 等。路由框架可以降低 Activity 之间的耦合,从而在不需要关心目标 Activity 的具体实现类, 利用协议完成跳转。

ActivityRouter使用方法

在AndroidManifest.xml配置

<activity
    android:name="com.github.mzule.activityrouter.router.RouterActivity"
    android:theme="@android:style/Theme.NoDisplay">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="mzule" /><!--改成自己的scheme-->
    </intent-filter>
</activity>

在需要配置的Activity上添加注解

@Router("main")
public class MainActivity extends Activity {
    ...
}

想要跳转到 MainActivity ,只要调用以下代码即可

Routers.open(context, "mzule://main")

如果想用 @Router 来调用方法

@Router("logout")
public static void logout(Context context, Bundle bundle) {
    Toast.makeText(context, "logout", Toast.LENGTH_SHORT).show();
}

源码解析

ActivityRouter 工程的结构如下

 

  • activityrouter: 路由跳转的具体实现代码
  • annotaition: 路由注解
  • app: 路由 demo
  • app_module: 路由 demo module
  • compiler: 注解处理
  • stub: 壳 module

annotation

先来看看 Router 的注解

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.CLASS)
public @interface Router {

    String[] value();

    String[] stringParams() default "";

    String[] intParams() default "";

    String[] longParams() default "";

    String[] booleanParams() default "";

    String[] shortParams() default "";

    String[] floatParams() default "";

    String[] doubleParams() default "";

    String[] byteParams() default "";

    String[] charParams() default "";

    String[] transfer() default "";
}

@Router 定义了该 Activity 路由的名字以及一些参数,这里可以注意到 @Retention 是 CLASS ,所以后面肯定在编译期间利用 Processor 来解析 @Router 生成路由表的。

另外,看到 @Target 是 ElementType.TYPE 和 ElementType.METHOD ,其实 @Router 除了跳转 Activity 之外,还有一个功能就是可以执行方法,只要在方法加上 @Router 即可。

路由表的生成源码我们到后面再讲,先来看看有了协议之后,Routers 是如何实现跳转 Activity 的。

activityrouter

public class Routers {

    ...

    public static boolean open(Context context, String url) {
        return open(context, Uri.parse(url));
    }
    
    public static boolean open(Context context, String url, RouterCallback callback) {
        return open(context, Uri.parse(url), callback);
    }
    
    public static boolean open(Context context, Uri uri) {
        return open(context, uri, getGlobalCallback(context));
    }
    
    public static boolean open(Context context, Uri uri, RouterCallback callback) {
        return open(context, uri, -1, callback);
    }
    
    public static boolean openForResult(Activity activity, String url, int requestCode) {
        return openForResult(activity, Uri.parse(url), requestCode);
    }
    
    public static boolean openForResult(Activity activity, String url, int requestCode, RouterCallback callback) {
        return openForResult(activity, Uri.parse(url), requestCode, callback);
    }
    
    public static boolean openForResult(Activity activity, Uri uri, int requestCode) {
        return openForResult(activity, uri, requestCode, getGlobalCallback(activity));
    }
    
    public static boolean openForResult(Activity activity, Uri uri, int requestCode, RouterCallback callback) {
        return open(activity, uri, requestCode, callback);
    }
    
    ...

}

可以看到不同的 open openForResult 方法重载,最后都是调用了 open(Context context, Uri uri, int requestCode, RouterCallback callback) 。那么接着跟踪:

private static boolean open(Context context, Uri uri, int requestCode, RouterCallback callback) {
    boolean success = false;
    // 如果有 callback 在跳转前回调 
    if (callback != null) {
        if (callback.beforeOpen(context, uri)) {
            return false;
        }
    }
    // 执行路由跳转
    try {
        success = doOpen(context, uri, requestCode);
    } catch (Throwable e) {
        e.printStackTrace();
        if (callback != null) {
            // 错误回调
            callback.error(context, uri, e);
        }
    }
    // 成功或失败回调
    if (callback != null) {
        if (success) {
            callback.afterOpen(context, uri);
        } else {
            callback.notFound(context, uri);
        }
    }
    return success;
}

open 方法中有很多都是不同状态下 callback 的回调,真正跳转的逻辑放在了 doOpen 方法中。

private static boolean doOpen(Context context, Uri uri, int requestCode) {
    // 如果没有初始化的话,调用 Router.init 进行初始化路由表
    initIfNeed();
    // 解析 uri 得到对应的 path
    Path path = Path.create(uri);
    // 根据 path 去查找与之对应匹配的 mapping ,然后实现跳转
    for (Mapping mapping : mappings) {
        if (mapping.match(path)) {
            // 如果 activity 是空的,就说明是执行方法的
            if (mapping.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值