ARouter 是阿里开源的 Android 页面路由框架,主要解决大型项目中 Activity、Fragment、Service 等组件之间解耦的问题。
如果你做的是中大型 Android 项目(尤其是组件化、模块化项目),ARouter 几乎是最常见的路由框架之一。
一、为什么需要 ARouter?
先看没有 ARouter 的情况。
假设有三个模块:
app
│
├── login
├── user
└── order
订单模块需要跳转到登录页。
传统写法:
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
问题来了:
order
│
▼
login
order 模块必须依赖 login 模块。
如果越来越多模块互相依赖:
A -> B
A -> C
B -> C
C -> D
依赖关系越来越乱。
组件化项目希望:
A
B Router
C
D
大家都依赖 Router,而不是彼此依赖。
这就是 ARouter 存在的意义。
二、ARouter 的核心思想
ARouter 就像 Android 的 Uri。
例如:
https://www.baidu.com/user/login
对应页面:
LoginActivity
ARouter 也是类似:
/login/LoginActivity
跳转:
ARouter.getInstance()
.build("/login/LoginActivity")
.navigation();
你不用知道:
LoginActivity.class
只需要知道:
"/login/LoginActivity"
即可。
三、ARouter 工作流程
例如:
ARouter.getInstance()
.build("/user/detail")
.withString("id","100")
.navigation();
流程:
build()
│
▼
Postcard
│
▼
Warehouse
│
▼
找到 UserDetailActivity
│
▼
创建 Intent
│
▼
startActivity()
整个流程如下:
String Path
│
▼
RouteMeta
│
▼
Activity.class
│
▼
Intent
│
▼
Activity
四、ARouter 的组成
1、@Route
用于注册页面。
例如:
@Route(path = "/login/main")
public class LoginActivity extends AppCompatActivity {
}
path 就是唯一标识。
推荐格式:
/模块名/页面名
例如:
/login/main
/user/detail
/order/list
/home/main
不要写:
/abc
/test
/main
后期维护非常困难。
2、build()
构建一个路由。
ARouter.getInstance()
.build("/login/main");
实际上返回:
Postcard
类似:
Postcard
path
group
extras
3、navigation()
真正开始跳转。
例如:
ARouter.getInstance()
.build("/login/main")
.navigation();
最终内部还是:
startActivity(intent);
五、传递参数
ARouter 与 Intent 的使用方式非常相似。
例如:
ARouter.getInstance()
.build("/user/detail")
.withString("name","Tom")
.withInt("age",18)
.navigation();
接收:
@Route(path = "/user/detail")
public class UserActivity extends AppCompatActivity {
@Autowired
String name;
@Autowired
int age;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ARouter.getInstance().inject(this);
Log.d("TAG", name);
Log.d("TAG", age + "");
}
}
注意:
ARouter.getInstance().inject(this);
必须调用。
否则:
@Autowired
不会注入。
你之前问过
ARouter.getInstance().inject(this)什么时候调用,答案就是:在Activity或Fragment创建后、使用这些字段之前调用,通常放在onCreate()中setContentView()之后最合适。
六、Fragment 跳转
例如:
Fragment fragment =
(Fragment) ARouter.getInstance()
.build("/home/fragment")
.navigation();
对应:
@Route(path="/home/fragment")
public class HomeFragment extends Fragment{
}
七、Service 获取
例如:
定义接口:
public interface IUserService {
String getUserName();
}
实现:
@Route(path = "/service/user")
public class UserServiceImpl implements IUserService {
@Override
public String getUserName() {
return "Tom";
}
}
获取:
IUserService service =
(IUserService) ARouter.getInstance()
.build("/service/user")
.navigation();
service.getUserName();
模块之间无需直接依赖实现类。
八、拦截器(Interceptor)
可以统一处理登录校验、权限等。
例如:
订单页面
│
▼
Interceptor
│
├──已登录
│ │
│ ▼
│ OrderActivity
│
└──未登录
│
▼
LoginActivity
定义:
@Interceptor(priority = 1)
public class LoginInterceptor implements IInterceptor {
@Override
public void process(Postcard postcard,
InterceptorCallback callback) {
if (isLogin()) {
callback.onContinue(postcard);
} else {
callback.onInterrupt(null);
}
}
}
九、自动注入(Autowired)
例如:
@Autowired
String token;
其实最终还是:
getIntent().getStringExtra("token");
只是 ARouter 帮你生成了代码。
十、Provider(推荐)
大型项目中最常用。
例如:
UserModule
提供:
获取 Token
获取用户信息
退出登录
其他模块:
Order
Home
Message
都可以:
ARouter
↓
UserProvider
无需依赖 User 模块。
十一、初始化
Application:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
if (BuildConfig.DEBUG) {
ARouter.openLog();
ARouter.openDebug();
}
ARouter.init(this);
}
}
调试模式:
ARouter.openLog();
ARouter.openDebug();
正式版建议关闭。
十二、编译时原理(重点)
ARouter 最大优势之一是 编译时生成路由表,而不是运行时反射扫描。
例如:
@Route(path="/login/main")
public class LoginActivity {}
编译期间,APT(Annotation Processing)会生成类似代码:
public class ARouter$$Group$$login
implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put(
"/login/main",
RouteMeta.build(
LoginActivity.class
)
);
}
}
初始化时:
Warehouse.routes
中保存:
"/login/main"
│
▼
LoginActivity.class
调用:
navigation()
时:
String Path
│
▼
HashMap
│
▼
Activity.class
│
▼
Intent
因此查找速度快,避免了运行时大量反射。
十三、完整使用示例
// 定义页面
@Route(path = "/user/detail")
public class UserActivity extends AppCompatActivity {
@Autowired
String name;
@Autowired
int age;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ARouter.getInstance().inject(this);
Log.d("TAG", name);
Log.d("TAG", age + "");
}
}
跳转:
ARouter.getInstance()
.build("/user/detail")
.withString("name", "Tom")
.withInt("age", 18)
.navigation(this);
十四、ARouter 的优缺点
| 优点 | 缺点 |
|---|---|
| 页面解耦 | 学习成本比 Intent 高 |
| 支持组件化 | 需要配置注解处理器(APT/KSP) |
| 支持参数自动注入 | 项目规模小时收益不明显 |
| 支持拦截器 | 官方维护已不如早期活跃 |
| 支持 Service/Provider | 新项目有时会选择其他路由方案 |
面试高频问题
-
ARouter 为什么比直接使用
Intent更适合大型项目?- 通过路径而非类引用进行跳转,降低模块间依赖,利于组件化和模块化开发。
-
ARouter.getInstance().inject(this)有什么作用?什么时候调用?- 用于解析
@Autowired标注的字段并完成参数注入,应在Activity/Fragment创建完成后、使用这些字段之前调用,通常放在onCreate()中。
- 用于解析
-
ARouter 底层为什么性能较好?
- 使用注解处理器在编译期生成路由映射表,运行时直接查询映射并构建
Intent,避免了运行时扫描和大量反射。
- 使用注解处理器在编译期生成路由映射表,运行时直接查询映射并构建
-
ARouter 可以路由哪些组件?
- 不仅支持
Activity,还支持Fragment、Service/Provider,并提供拦截器、参数注入等能力。
- 不仅支持
如果你现在主要做 Android 面试,我还可以继续讲 ARouter 源码(路由表生成、Warehouse、LogisticsCenter、Postcard、navigation() 源码流程),这是高级 Android 面试中非常常见的考点。