系列文章:
路由框架ARouter使用及源码解析(一)
路由框架ARouter使用及源码解析(二)
文章目录
一、什么是路由?
路由是指路由器从一个接口上收到数据包,根据数据路由包的目的地址进行定向并转发到另一个接口的过程。—百度百科
以Android为例,各个组件module可以看成一个个网络,而路由就可以看成是各个模块页面跳转的中转站,除了中转以外,路由还可以过滤或拦截一些不安全或不规范的跳转。
二、阿里ARouter
官方定义:A framework for assisting in the renovation of Android componentization (帮助 Android App 进行组件化改造的路由框架)
其实Android的跳转已经提供了Intent,Intent不仅可以显示跳转,也可以隐式跳转。那么ARouter为什么还会存在呢?让我们对比一下原生跳转和路由跳转:
1、原生显示跳转必须依赖于类,强耦合,而隐式跳转需要都在AndroidManifest里集中注册,协作麻烦;而路由跳转通过URL索引,低耦合,协作方便;
2、原生在通过staryActivity启动跳转后就交由系统控制,并不能做拦截;路由跳转可以对跳转做过滤或拦截。
通过对比,我们发现路由特别适合用来做跳转(尤其是组件间的通信及跳转),下面就来看一下阿里ARouter的集成及使用吧~
2.1、配置&初始化
在app的build.config中配置:
compile 'com.alibaba:arouter-api:1.4.1'
annotationProcessor 'com.alibaba:arouter-compiler:1.2.2'
在各个需要使用ARouter模块的build.gradle的defaultConfig配置中加入:
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
注意:新版本已经改成AROUTER_MODULE_NAME来获取module名字了。
上面配置中,annotationProcessor用来声明注解解析器,arouter-compiler用来解析ARouter中的各个注解(后面会讲到),通过APT方式在编译期间自动生成class类,关于annotationProcessor可以查看下面这篇文章:
https://blog.csdn.net/xx326664162/article/details/68490059
配置完成后,进行初始化:
在自定义Application中进行初始化:
if (BuildConfig.DEBUG) {
// 打印日志
ARouter.openLog();
// 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
ARouter.openDebug();
}
// 尽可能早,推荐在Application中初始化
ARouter.init(this);
初始化完成后,就可以开始使用了~
2.1、基本跳转
以Activity跳转为例,比如从Activity1跳转到Activity2,首先在1、目标Activity2中:
@Route(path = MConstant.ACTIVITY2)
public class Activity2 extends Activity {
}
Activity2添加注解@Route,path是跳转路径,一般都写在统一的一个类中,方便维护:
public class MConstant {
public static final String ACTIVITY2 = "/main/activity2";
public static final String TRANSFER_KEY = "transfer_key";
}
2、在Activity1中进行ARouter注入并实现跳转:
public class Activity1 extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ARouter.getInstance().inject(this);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ARouter.getInstance().build(MConstant.ACTIVITY2).navigation();
}
});
}
上面就实现了简单的页面跳转,如果想传递参数,可以用下面的方式:
ARouter.getInstance().build(path).withString(MConstant.TRANSFER_KEY,"value").navigation();
withXXX处填的是参数的key和value (如果ARouter传递的是对象,首先该对象需要Parcelable或者Serializable序列化) ,navigation发射了路由跳转。在目标类中,通过注解@Autowired来获取传递值:
public class Activity2 extends Activity {
@Autowired(name = TRANSFER_KEY)
public String qrText;
}
2.3、获取Fragment实例
首先在Fragment上使用注解@Route
@Route(path = "/test/fragment")
public class BlankFragment extends Fragment {
}
获取Fragment实例:
Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation();
通过上面的代码就可以获取Fragment的实例,这在跨模块中使用Fragment是很有用的。
2.4、进阶用法之拦截器&通过URL跳转
拦截器:
@Interceptor(priority = 1)
public class MyInterceptor implements IInterceptor {
private Context context;
@Override
public void process(Postcard postcard, InterceptorCallback callback) {
if (MConstant.ACTIVITY2.equals(postcard.getPath())) {
//如果是跳转Activity2,则拦截
callback.onInterrupt(null);
} else {
callback.onContinue(postcard);
}
}
@Override
public void init(Context context) {
this.context = context;
}
}
拦截器需要实现IInterceptor并通过注解@Interceptor来声明,其中多个拦截器的优先级根据priority来判断,值越小优先级越高。
通过URL跳转:
Uri testUriMix = Uri.parse("arouter://m.aliyun.com/main/activity2");
ARouter.getInstance().build(testUriMix)
.withString("key1", "value1")
.navigation();
跟上面介绍的普通跳转几乎一样,上面是用的path跳转,而这里使用的是URL跳转,一般在自定义协议(如webview)时,使用URL跳转非常的方便,并且可以对URL做拦截、转换等。
2.5、服务管理
比如ModuleA中想调用ModuleB中的方法,在公共引用库中声明接口并继承IProvider:
public interface IModuleService extends IProvider {
String getModuleName();
}
在ModuleB中定义接口实现类:
@Route(path = MConstant.MODULE_SERVICE)
public class ChatModuleService implements IModuleService {
@Override
public String getModuleName() {
return "chatModule";
}
@Override
public void init(Context context) {
}
}
在ModuleA中调用:
//1、通过类名调用服务
IModuleService service = ARouter.getInstance().navigation(IModuleService.class);
String getName = service.getModuleName();
Log.e("TTT", "getName is " + getName);
//2、通过路径名称调用服务
IModuleService service1 = (IModuleService) ARouter.getInstance().build(MConstant.MODULE_SERVICE).navigation();
String getName1 = service1.getModuleName();
Log.e("TTT", "getName1 is " + getName1);
上面两种方式都可以最终得到ModuleB中的数据。
2.6、降级方案
ARouter.getInstance().build("/xxx/xxx").navigation(this, new NavCallback() {
@Override
public void onFound(Postcard postcard) {
Log.d("ARouter", "找到了");
}
@Override
public void onLost(Postcard postcard) {
Log.d("ARouter", "找不到了");
}
@Override
public void onArrival(Postcard postcard) {
Log.d("ARouter", "跳转完了");
}
@Override
public void onInterrupt(Postcard postcard) {
Log.d("ARouter", "被拦截了");
}
});
当跳转失败时,可以通过回调得到结果并做相应处理。
三、引用
【1】ARouter: https://github.com/alibaba/ARouter
【2】APT、annotationProcessor、android-apt、Provided、自定义注解:
https://blog.csdn.net/xx326664162/article/details/68490059