介绍
FssRouter让路由变得更简单,更规范。自定义路由API使得路由参数与路由信息一目了然,更便于管理。FssRouter框架还提供了自动创建路由API的方式,你只需要一个注解便能声明一种路由方式,更简单方便。
gitHub地址:https://github.com/gongbox/fss
背景
在Android开发中,如果要从当前Activity跳转到下一个Activity,你可能会直接使用Intent的方式跳转,如下:
Intent intent = new Intent(this,XXXActivity.class);
intent.putExtra("name","value"); //传递参数
startActivity(intent);
或者你也可能使用阿里的ARouter路由框架,如下:
ARouter.getInstance().build("/xxx/xxx")
.withString("name","value") //传递参数
.navigation(XXXActivity.class);
不管使用哪种方式,你都会发现如下问题:
1,路由要携带的参数有哪些?各个参数的key值是什么?哪些参数是必传?这些参数是什么意思...
2,对应的Activity是显示启动还是隐式启动,如果是隐式启动对应的action是什么,如果有requestCode,category,flags又该设置为多少
3,无法统一管理路由,到处可见的Intent与startActivity等等,路由方式很随意,哪里想跳就在哪儿写,想传什么参数就传什么。
4,代码量多,传的参数越多,要跳转的地方越多,代码量也就越多。
在这种背景下,笔者便有了灵感,写出了FssRouter路由框架,我们看看FssRouter是怎么解决这些问题的。
接入
在根项目的build.gradle文件中添加仓库地址
allprojects {
repositories {
...
maven { url 'https://www.jitpack.io' }
}
}
对应模块添加依赖
implementation 'com.github.gongbox.fss:router-api:1.0.33'
annotationProcessor 'com.github.gongbox.fss:router-compiler:1.0.33'
使用
我们先看一下使用自定义路由API的方式,使用这种方式需要声明一个接口,在接口中声明路由信息。
现在假设我们有两个Activity,分别是MainActivity,DetailActivity,
现在的代码是这样:
public class MainActivity extends AppCompatActivity {
...
}
public class DetailActivity extends AppCompatActivity {
...
}
然后我们声明一个java接口,接口名随意,这里为ITestRouteApi
@RouteApi("test") //定义为路由Api,“test”为这个路由api的分组
public interface ITestRouteApi {
@RouteActivity(DetailActivity.class) //定义路由的目的Activity
void navigateToDetailActivity(Context context); //第一个参数必须为Context类型
}
声明上面的接口api后,然后再编译项目,然后我们就可以使用如下的方式进行路由了。
public class MainActivity extends AppCompatActivity {
...
void xxx(){
//使用下面的方式进行路由
FssRouteApi.TEST.navigateToDetailActivity(MainActivity.this);
}
}
上面是一个简单的例子,我们在看看其他情况。
1,隐式意图启动
@RouteApi("test") //定义为路由Api,“test”为这个路由api的分组
public interface ITestRouteApi {
@RouteActivity(action = "com.fss.route.detail")
void navigateToDetailActivity(Context context);
}
2,携带路由参数
@RouteApi("test") //定义为路由Api,“test”为这个路由api的分组
public interface ITestRouteApi {
@RouteActivity(action = "com.fss.route.detail")
void navigateToDetailActivity(Context context, @Extra("value") int value);
}
3,携带默认路由参数
@RouteApi("test") //定义为路由Api,“test”为这个路由api的分组
public interface ITestRouteApi {
@RouteActivity(DetailActivity.class)
@DefaultExtra(
name = "defaultValue",
defaultValue = "hello",
type = String.class
)
void navigateToDetailActivity(Context context);
}
4,设置requestCode,category,flags,路由动画等
@RouteApi("test") //定义为路由Api,“test”为这个路由api的分组
public interface ITestRouteApi {
@RouteActivity(
value = DetailActivity.class, //设置路由的目标Activity
requestCode = 1234, //设置requestCode
)
void navigateToDetailActivity1(Context context);
@RouteActivity(
value = DetailActivity.class, //设置路由的目标Activity
category = Intent.CATEGORY_DEFAULT, //设置category
)
void navigateToDetailActivity2(Context context);
@RouteActivity(
value = DetailActivity.class, //设置路由的目标Activity
flags = Intent.FLAG_ACTIVITY_CLEAR_TASK, //设置falgs
)
void navigateToDetailActivity3(Context context);
@RouteActivity(
value = DetailActivity.class, //设置路由的目标Activity
enterAnim = android.R.anim.fade_in, //设置activity进入动画
exitAnim = android.R.anim.fade_out //设置activity退出动画
)
void navigateToDetailActivity4(Context context);
}
5,携带Uri,设置type等
@RouteApi("test") //定义为路由Api,“test”为这个路由api的分组
public interface ITestRouteApi {
@RouteActivity(action = Intent.ACTION_VIEW)
void routeToView(Context context, Uri data);
@RouteActivity(
action = Intent.ACTION_GET_CONTENT,
requestCode = 2,
category = Intent.CATEGORY_OPENABLE,
type = "video/*")
void navigateToGetContent(Context context);
}
自动创建Api
上面展示了如何自定义一个路由Api,并如何进行路由。接下来我们看一种更简单的方式实现路由。
我们在的DetailActivity上声明一个注解@Route,编译项目
@Route
public class DetailActivity extends AppCompatActivity {
...
}
然后我们在MainActivity中便可以直接这样来跳转到DetailActivity了
public class MainActivity extends AppCompatActivity {
...
void xxx(){
//使用下面的方式进行路由
FssRouteApi.DEFAULT.navigateToDetailActivity(MainActivity.this);
}
}
这是因为在编译时,FssRouter会帮我们自动生成对应的路由Api,如下:
image.png
IDefaultRouteApi.java文件的具体内容如下:
public interface IDefaultRouteApi {
@RouteActivity(DetailActivity.class)
void navigateToDetailActivity(Context context);
}
因此,使用@Route注解便可以帮我们自动生成路由Api,这使得我们不必自定义路由API便可以实现路由,这种方式相对更简单,使用@Route注解,你几乎可以完成上面自定义Api的所有工作。笔者也更推荐使用这种方式,下面将介绍如何使用@Route注解。
1.携带参数
@Route(routeExtras = {
@RouteExtra(name = "value", type = String.class)
})
public class DetailActivity extends AppCompatActivity {
...
}
其中name为对应参数的key,type为对应参数的类型,默认为Object.class,支持多个参数。
对应生成的API为:
public interface IDefaultRouteApi {
@RouteActivity(DetailActivity.class)
void navigateToDetailActivity(Context context, @Extra("value") String value);
}
2.携带默认参数
@Route(defaultExtras = {
@DefaultExtra(name = "defaultValue", defaultValue = "hello" , type = String.class)
})
public class DetailActivity extends AppCompatActivity {
...
}
默认参数即是默认携带的参数,只支持基本数据类型,默认为String类型,支持多个默认参数。
对应生成的API为:
public interface IDefaultRouteApi {
@RouteActivity(DetailActivity.class)
@DefaultExtra(name = "defaultValue", defaultValue = "hello" , type = String.class)
void navigateToDetailActivity(Context context);
}
3.隐式启动
@Route(action = "com.gongbo.fss.route.detail")
public class DetailActivity extends AppCompatActivity {
...
}
这里便会以隐式意图去启动这个Activity,但是注意你还是需要在AndroidManifest.xml中配置这个Activity支持隐式启动。
对应生成的API为:
public interface IDefaultRouteApi {
@RouteActivity(action = "com.gongbo.fss.route.detail")
void navigateToDetailActivity(Context context);
}
4. 设置分组
@Route(group = "test")
public class DetailActivity extends AppCompatActivity {
...
}
每一个分组都会对应FssRouteApi类中的一个静态常量,test分组即对应FssRouteApi.TEST,如果没有设置分组,默认为default分组(FssRouteApi.DEFAULT)。此外,相同分组的Api将定义在同一个文件内,如IDefaultRouteApi.class。
对应生成的API为:
public interface ITestRouteApi {
@RouteActivity(DetailActivity.class)
void navigateToDetailActivity(Context context);
}
5. 设置路由方法名
@Route(name = "navigateTest")
public class DetailActivity extends AppCompatActivity {
...
}
路由方法默认为 "navigateTo"+路由目的类的类名称,通过设置name你可以设置自己想要的名称。
对应生成的API为:
public interface ITestRouteApi {
@RouteActivity(DetailActivity.class)
void navigateTest(Context context);
}
6. 设置flags,category,requestCode等
@Route(
category = Intent.CATEGORY_DEFAULT,
flags = Intent.FLAG_ACTIVITY_CLEAR_TASK,
requestCode = 1234
)
public class DetailActivity extends AppCompatActivity {
...
}
对应生成的API为:
public interface ITestRouteApi {
int REQUEST_CODE_TO_DETAIL_ACTIVITY = 1234;
@RouteActivity(
value = DetailActivity.class,
category = Intent.CATEGORY_DEFAULT,
flags = Intent.FLAG_ACTIVITY_CLEAR_TASK,
requestCode = REQUEST_CODE_TO_DETAIL_ACTIVITY)
void navigateToDetailActivity(Context context);
}
7,其他,设置路由动画,为路由方法添加注释等等
下面是一个比较完整的例子
@Route(
//设置路由名称
name = "navigateTest",
//设置分组
group = "detail",
//添加requestCode
requestCode = 1234,
//设置category
category = Intent.CATEGORY_DEFAULT,
//设置falgs
flags = Intent.FLAG_ACTIVITY_CLEAR_TASK,
//添加参数
routeExtras = {
@RouteExtra(name = "value", type = String.class, desc = "参数注释")
},
//添加默认参数
defaultExtras = {
@DefaultExtra(name = "defaultValue", defaultValue = "hello")
},
//activity进入动画
enterAnim = android.R.anim.fade_in,
exitAnim = android.R.anim.fade_out,
//添加注释
desc = "示例"
)
public class DetailActivity extends AppCompatActivity {
...
}
对应生成的API为:
public interface IDetailRouteApi {
int REQUEST_CODE_TO_DETAIL_ACTIVITY = 1234;
/**
* 示例
* @value 参数注释
*/
@RouteActivity(
value = RouteDetailActivity.class,
requestCode = REQUEST_CODE_TO_ROUTE_DETAIL_ACTIVITY,
category = {"android.intent.category.DEFAULT"},
flags = 32768,
enterAnim = 17432576,
exitAnim = 17432577
)
@DefaultExtra(
name = "defaultValue",
defaultValue = "hello",
type = String.class
)
void navigateTest(Context context, @Extra("value") String value);
}
这里提一下,@Route注解不仅可以声明在Activity上,也可以声明在Service或Fragment上,FssRouter同样支持路由到Service或Fragment,但部分属性不支持Service或Fragment。
而且你也可以在同一个Activity(或Service,Fragment)上添加多个@Route注解,以提供多种路由方式
其他
1,自定义配置
通过在build.gradle中defaultConfig中添加如下配置进行自定义修改
javaCompileOptions {
annotationProcessorOptions {
arguments = [
MODULE_NAME : "fss", //模块名(重要,多模块时一定要填写)
NAVIGATE_PREFIX : "navigateTo", //路由方法前缀
NAVIGATE_SUFFIX : "", //路由方法后缀
BUILD_INTENT_PREFIX: "buildIntentFor",//构建Intent方法前缀
BUILD_INTENT_SUFFIX: "", //构建Intent方法后缀
API_PREFIX : "I", //路由接口名常量前缀
API_SUFFIX : "RouteApi", //路由接口名常量后缀
GROUP_PREFIX : "", //路由分组常量前缀
GROUP_SUFFIX : "", //路由分组常量后缀
DEFAULT_GROUP : "default", //默认分组名
ROUTE_API_PREFIX : "", //接口前缀
ROUTE_API_SUFFIX : "RouteApi", //接口后缀
]
}
}
以上展示的是默认值,大多数参数通常情况下你都不需要自定义,但要注意,MODULE_NAME一定要配置,尤其是在项目中存在多个使用FssRouter的模块时。在下节的多组件支持中会讲解。
2,多组件支持
通过在各组件/模块中配置不同的MODULE_NAME参数实现,这样相应模块生成的api将放在不同的包名下,默认是com.fss.router,修改后将为com.MODULE_NAME的值.router。同时相应的Api的接口名也将会修改,默认为FssRouteApi,修改后将为
MODULE_NAME的值+ROUTE_API_SUFFIX
3,同一个Activity生成多个跳转方式
如果你使用的是Java8
@Route(name = "navigateTest")
@Route(group = "test")
@Route(action = "com.fss.hello")
public class DetailActivity extends AppCompatActivity {
...
}
如果不是使用的Java8
@Routes(value = {
@Route(name = "routeTest"),
@Route(group = "test"),
@Route(action = "com.fss.hello")
})
public class DetailActivity extends AppCompatActivity {
...
}
4,我想查看Activity的返回值,有没有更好的方式?
我们只需要将withResultCallBack设为true即可
@Route(requestCode = 1234, withResultCallBack = true)
对应生成的DefaultRouteApi
int REQUEST_CODE_TO_DETAIL_ACTIVITY = 1234;
@RouteActivity(
value = DetailActivity.class,
requestCode = REQUEST_CODE_TO_DETAIL_ACTIVITY
)
void navigateToDetailActivity(Context context, OnActivityResult onActivityResult);
可以看到上面的方法多了一个OnActivityResult类型的参数
然后我们就可以这样使用:
FssRouteApi.DEFAULT.navigateToDetailActivity(this, new OnActivityResult() {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
//在这个方法会在该Activity返回后调用
}
});
不过,要实现这样的功能,我们还需要在MainActivity里的onActivityResult方法里添加一行代码:
public class MainActivity extends AppCompatActivity {
@Override
protected void onActivityResult(int requestCode, int resultCode,@Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//这里必须添加,否则不会起作用
FssRouter.onActivityResult(requestCode, resultCode, data);
}
}
最后
总结一下:
一,FssRouter使用了类似retrofit的方式管理路由,路由信息清晰明了。
二,相同分组的路由声明在同一接口文件中,便于管理
三,使用时只需一行代码便可以实现路由,路由更方便。
如果你还有其他疑问或建议,欢迎与作者反馈,如果觉得不错,请点个赞,给颗星,谢谢。
更多FSS框架:
- Android开发利器-FSS开源框架之绑定
- Android开发利器-FSS开源框架之fss_common
- Android开发利器-FSS开源框架之方法运行优先级
- Android开发利器-FSS开源框架之ListView,RecyclerView适配器
如果想要了解fss框架的具体使用,我为大家提供了demo工程
网友评论