今天,在此记录一下路由框架,在众多的路由框架中,阿里ARouter的给我一种亲切感。
ARouter是阿里巴巴开源的Android平台中对页面、服务提供路由功能的中间件,提倡的是简单且够用。
原生的路由方案的问题
自定义路由组件目标
ARouter路由框架优势
添加依赖和配置(找最新的版本)
android {
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [ moduleName : project.getName() ]
}
}
}
}
dependencies {
// 替换成最新版本, 需要注意的是api
// 要与compiler匹配使用,均使用最新版可以保证兼容
implementation 'com.alibaba:arouter-api:1.4.1'
annotationProcessor 'com.alibaba:arouter-compiler:1.2.2'
...
}
添加注解及初始化
在Application中ARouter初始化
private Boolean isDebug = true;
@Override
public void onCreate() {
super.onCreate();
if (isDebug) {
// 这两行必须写在init之前,否则这些配置在init过程中将无效
// 打印日志
ARouter.openLog();
// 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
ARouter.openDebug();
}
// 尽可能早,推荐在Application中初始化
ARouter.init(instance);
}
在需要跳转的Activity上进行注解配置
// 在支持路由的页面上添加注解(必选)
// 这里的路径需要注意的是至少需要有两级,/xx/xx
@Route(path = "/**/ARouterActivity")
public class ARouterActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_arouter);
//....
}
应用中的简单跳转
ARouter.getInstance().build("/**/ARouterActivity").navigation();
应用中携带参数的跳转
ARouter.getInstance().build("/**/ARouter2Activity")
.withString("id","01")
.withInt("age",18)
.navigation();
在目标Activity中接受相关的参数
@Route(path = "/**/ARouterActivity")
public class ARouterActivity extends Activity {
@Autowired
public String id;
@Autowired
int age;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ARouter.getInstance().inject(this);
// ARouter会自动对字段进行赋值,无需主动获取
Log.d("param", id + age);
}
}
其中,下面这个代码是安卓组件接收方必须添加的代码。
ARouter.getInstance().inject(this);
Activity之间传递自定义对象
// 自定义类
public class Test implements Serializable{
public String id;
//...
}
//跳转至页面
ARouter.getInstance().build("/**/ARouterActivity")
.withSerializable("test", test)
.navigation();
//目标页面
@Autowired
Test test;
通过Url进行跳转
在AndroidManifest.xml中进行如下配置:
新建一个Activity用于监听Schame事件,之后直接把url传递给ARouter
@Route(path = "/**/SchameFilterActivity")
public class SchameFilterActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Uri uri = getIntent().getData();
ARouter.getInstance().build(uri).navigation();
finish();
}
}
设置拦截器
@Interceptor(priority = 2, name = "测试拦截器")
public class TestInterceptor implements IInterceptor {
@Override
public void process(Postcard postcard, InterceptorCallback callback) {
...
// 处理完成,交还控制权
callback.onContinue(postcard);
// 觉得有问题,中断路由流程
// callback.onInterrupt(new RuntimeException("我觉得有点异常"));
// 以上两种至少需要调用其中一种,否则不会继续路由
}
@Override
public void init(Context context) {
// 拦截器的初始化,会在sdk初始化的时候调用该方法,仅会调用一次
}
}
监听路由跳转结果
// 使用两个参数的navigation方法,可以获取单次跳转的结果
ARouter.getInstance().build("/**/Activity").navigation(this, new NavigationCallback() {
@Override
public void onFound(Postcard postcard) {
//...
}
@Override
public void onLost(Postcard postcard) {
//...
}
});
获取Fragment的对象
// 获取Fragment
Fragment fragment = (Fragment) ARouter.getInstance().build("/**/fragment").navigation();
// 构建标准的路由请求
ARouter.getInstance().build("/**/main").navigation();
// 构建标准的路由请求,并指定分组
ARouter.getInstance().build("/**/main", "ap").navigation();
// 构建标准的路由请求,通过Uri直接解析
Uri uri;
ARouter.getInstance().build(uri).navigation();
// 构建标准的路由请求,startActivityForResult
// navigation的第一个参数必须是Activity,第二个参数则是RequestCode
ARouter.getInstance().build("/**/main", "ap").navigation(this, 5);
// 直接传递Bundle
Bundle params = new Bundle();
ARouter.getInstance()
.build("/**/main")
.with(params)
.navigation();
// 指定Flag
ARouter.getInstance()
.build("/**/main")
.withFlags();
.navigation();
// 获取Fragment
Fragment fragment = (Fragment) ARouter.getInstance().build("/**/fragment").navigation();
// 对象传递
ARouter.getInstance()
.withObject("key", new TestObj("Jack", "Rose"))
.navigation();
// 觉得接口不够多,可以直接拿出Bundle赋值
ARouter.getInstance()
.build("/home/main")
.getExtra();
// 转场动画(常规方式)
ARouter.getInstance()
.build("/test/activity2")
.withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)
.navigation(this);
// 转场动画(API16+)
ActivityOptionsCompat compat = ActivityOptionsCompat.
makeScaleUpAnimation(v, v.getWidth() / 2, v.getHeight() / 2, 0, 0);
// ps. makeSceneTransitionAnimation 使用共享元素的时候,需要在navigation方法中传入当前Activity
ARouter.getInstance()
.build("/**/activity")
.withOptionsCompat(compat)
.navigation();
// 使用绿色通道(跳过所有的拦截器)
ARouter.getInstance().build("/**/main").greenChannel().navigation();
// 使用自己的日志工具打印日志
ARouter.setLogger();
初始化中的其他配置
ARouter.openLog(); // 开启日志
ARouter.openDebug(); // 使用InstantRun的时候,需要打开该开关,上线之后关闭,否则有安全风险
ARouter.printStackTrace(); // 打印日志的时候打印线程堆栈
路由中的分组概念
@Route(path = "/**/activity", group = "app")
添加混淆规则
-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}
# 如果使用了 byType 的方式获取 Service,需添加下面规则,保护接口
-keep interface * implements com.alibaba.android.arouter.facade.template.IProvider
# 如果使用了 单类注入,即不定义接口实现 IProvider,需添加下面规则,保护实现
-keep class * implements com.alibaba.android.arouter.facade.template.IProvider
最后推荐文章:开源最佳实践:Android平台页面路由框架ARouter