文章目录
简介
介绍
ARouter 是阿里巴巴开源的一款 Android 路由框架,专为组件化架构设计,用于模块之间的页面跳转和服务通信。
ARouter 是路由系统,给无依赖的双方提供通信和路由的能力
作用
- 页面路由(页面跳转)
- 通过简单的路由配置,实现模块间页面跳转,避免直接依赖具体类,降低耦合度。
- 支持跨模块的页面跳转,即使页面所属模块在不同的
APK
中。
- 服务发现与调用
- 提供服务注册与发现机制,可以实现模块间的接口调用。
- 通过依赖注入机制简化服务调用流程,提升开发效率。
- 动态传参
- 支持页面跳转时传递参数(基本类型、对象等)。
- 支持通过注解方式接收参数,省去解析逻辑。
原理
关系
- 1.注册
B界面将类的信息,通过key-value的形式,注册到arouter中。
- 2.查询
A界面将类信息与额外信息(传输参数、跳转动画等),通过key传递至arouter中,并查询对应需要跳转类的信息。
- 3.结合
将A界面类信息、参数与B界面的类信息进行封装结合。
- 4.跳转
将结合后的信息,使用startActivity实现跳转。
使用
添加依赖和配置
android {
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
}
dependencies {
implementation 'com.alibaba:arouter-api:x.x.x'
annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'
...
}
在 gradle.properties
文件中添加如下行来启用 Jetifier:
主要用于自动将旧版的 Android 库(即基于 Support Library
的库)迁移为 AndroidX
兼容版本。
android.enableJetifier=true
初始化SDK
if (isDebug()) {
// 这两行必须写在init之前,否则这些配置在init过程中将无效
ARouter.openLog(); // 打印日志
ARouter.openDebug(); // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
}
ARouter.init(mApplication); // 尽可能早,推荐在Application中初始化
我们可以在Application中初始化
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// 仅在调试模式下开启日志和调试模式
if(BuildConfig.DEBUG){
ARouter.openLog();
ARouter.openDebug();
}
ARouter.init(this);
}
}
添加注解在目标界面
// 在支持路由的页面上添加注解
// 路径注意至少需有两级,/xx/xx
@Route(path = "/test/second")
public class SecondActivity extends AppCompatActivity {
跳转界面不带参
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startActivity(View view) {
ARouter.getInstance().build("/test/SecondActivity")
.navigation();
}
}
这里跳转放在onCreate里报错:可能是因为ARouter 未初始化完成,初始化放在onCrete里就好了
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 仅在调试模式下开启日志和调试模式 if(BuildConfig.DEBUG){ ARouter.openLog(); ARouter.openDebug(); } ARouter.init(getApplication()); ARouter.getInstance().build("/test/SecondActivity") .navigation(); } }
跳转界面含参
// 1
ARouter.getInstance().build("/test/SecondActivity")
.withString("key1", "123")
.withBoolean("key2", false)
.navigation();
// 2
@Route(path = "/test/SecondActivity")
public class SecondActivity extends AppCompatActivity {
public String key1;
@Autowired(name = "key2")
public boolean aBoolean;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
ARouter.getInstance().inject(this);
Log.d("SecondActivityTag", key1 + " " + aBoolean);
}
}
处理返回结果
如果需要在跳转到新页面并返回结果,可以使用 ARouter.getInstance().build()
方法构建路由请求时,调用 navigation()
方法的重载版本,传入一个 NavigationCallback
回调接口来处理返回结果
ARouter.getInstance().build("/main/selectActivity")
.navigation(this, new NavigationCallback() {
@Override
public void onFound(Postcard postcard) {
// 找到目标页面
}
@Override
public void onLost(Postcard postcard) {
// 找不到目标页面
}
@Override
public void onArrival(Postcard postcard) {
// 到达目标页面
}
@Override
public void onInterrupt(Postcard postcard) {
// 路由被拦截
}
});
源码
基本流程
getInstance()
ARouter.getInstance().build("/test/SecondActivity")
.navigation();
双检锁,获取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;
}
}
build()
这里使用了门面模式。外部调用者只需与 ARouter
交互,获取路由对象,不需要了解 _ARouter
内部如何管理单例、如何创建 Postcard
等。
build返回一个Postcard,
// ARouter.java
public Postcard build(String path) {
return _ARouter.getInstance().build(path);
}
// _ARouter.java
protected Postcard build(String path) {
if (TextUtils.isEmpty(path)) {
throw new HandlerException(Consts.TAG + "Parameter is invalid!");
} else {
// 预处理替换: 有需求来对 path 做统一的预处理就实现 PathReplaceService
PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
if (null != pService) {
path = pService.forString(path);
}