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.