介绍
fss_router是为了更好地管理路由。
gitHub地址:https://github.com/gongbox/fss_router
###背景
在Aandroid开发中,如果想从A.activity跳转到B.activity,那么一般你会这么写:
Intent intent = new Intent(A.this,B.class);
startActivity(intent);
当工程比较小时,你觉得没有问题,但是当页面变得非常多时,你可能就会越来越感到麻烦:
1,XxxActivity是显示启动还是隐式启动,如果是隐式启动,对应的action是什么?
2,XxxActivity的参数需要传哪些?每个参数对应的key值是什么?每个参数是什么意思?是是否必传?
3,XxxActivity的flags,category分别需要传什么?
4,如果需要获取返回信息,那XxxActivity的requestCode应该传什么呢?
…
很可能,带着这些疑问,你需要跳转到XxxActivity看源码才能知道,那如果这个Activity不是你写的呢?或者时间久了你又记不清了呢?
总之,这是一个相当麻烦的事。在这种背景下,FssRouter便有了,我们看看它是怎么解决这些问题的呢。
现在假设我们有有个Activity,分别是MainActivity,DetailActivity,
现在的代码是这样:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
@RouteConfig
public class DetailActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
}
}
然后我们导入我们的fss_router框架
implementation 'com.github.gongbox:fss_run_router:1.0.49'
接着,我们在DetailActivity上声明一个注解@ RouteConfig,然后编译一下
@RouteConfig
public class DetailActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
}
}
然后我们在MainActivity中便可以这样来跳转到DetailActivity了
FssRouteApi.DEFAULT_ROUTE_API.routeToDetailActivity(MainActivity.this);
你很可能会有点疑问,上面的方法是怎么来的呢?
其实, FssRouteApi是fss框架在编译期帮我们生成的一个类,只要你在某一个类上声明了@ RouteConfig注解,那么就会在为你生成相应的接口。
我们现在点进去看一下routeToDetailActivity这个方法是在哪儿声明的。
@RouteApi
public interface DefaultRouteApi {
@Route(to = DetailActivity.class)
void routeToDetailActivity(Context formObj);
}
我们发现,这儿是声明了一个接口DefaultRouteApi,里面定义了我们的routeToDetailActivity方法。具体里面怎么跳转的,我们先不讨论。
这样以来,跳转Activity已经解决了,但是我们实际中一般不会这么简单,接下来我们看看更复杂一点的用法。
1,使用action的方式启动
@RouteConfig(action = "com.fss.detail")
对应生成的DefaultRouteApi
@RouteApi
public interface DefaultRouteApi {
@Route(action = "com.fss.detail")
void routeToDetailActivity(Context formObj)
}
然后,这样就会使用隐式意图启动这个Activity了
2,指定requestCode,flags,category等等
@RouteConfig(
action = "com.fss.detail",
requestCode = 1234,
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP,
category = Intent.CATEGORY_DEFAULT)
对应生成的DefaultRouteApi
@RouteApi
public interface DefaultRouteApi {
int REQUEST_CODE_TO_DETAIL_ACTIVITY = 1234;
@Route(
action = "com.fss.detail",
requestCode = REQUEST_CODE_TO_DETAIL_ACTIVITY,
category = {"android.intent.category.DEFAULT"},
flags = {67108864}
)
void routeToDetailActivity(Context formObj)
}
然后,这样你调用这个方法时就会携带上你定的其他信息了,另外说明下requestCode会在该接口内定义成常量,这样你其他地方就直接可以使用这个常量了,再也不用担心搞忘了
3,携带参数
@RouteConfig(routeExtras = {
@RouteExtra(name = "value", type = String.class)
})
对应生成的DefaultRouteApi
@Route(activity = DetailActivity.class)
void routeToDetailActivity(Context formObj, @Extra(name = "value") String value);
然后,你在调用这个方法时,在对应的位置放入自己想要传递的参数,这个参数就会使用value作为key值传递。
另外,FssRouter支持默认参数传递,比如下面的例子:
@Route(activity = DetailActivity.class)
void routeToDetailActivity(Context formObj, @Extra(name = "value") String value);
对应生成的DefaultRouteApi
@Route(activity = DetailActivity.class )
@DefaultExtra(
name = "value",
defaultValue = "123",
type = Integer.class
)
void routeToDetailActivity(Context formObj);
这样,你再调用这个方法时,就会自动加入key值为value的一个Integer类型参数作为参数传递给DetailActivity。
4,为每个跳转添加注释
@RouteConfig(desc = "跳转到详情页")
对应生成的DefaultRouteApi
/**
* 跳转到详情页 */
@Route(
activity = DetailActivity.class
)
void routeToDetailActivity(Context formObj);
5,为跳转自定义名字
@RouteConfig(name = "routeTest")
对应生成的DefaultRouteApi
@Route(activity = DetailActivity.class)
void routeTest(Context formObj);
6,我想将跳转方法进行分组,相同分组的方法放到同一个接口文件中,便于管理
@RouteConfig(group = "test")
对应对生成一个名为TestRouteApi的接口文件
@RouteApi
public interface TestRouteApi {
@Route(activity = DetailActivity.class)
void routeToDetailActivity(Context formObj);
}
7,同一个Activity生成多个跳转方式
如果你使用的是Java8
@RouteConfig(name = "routeTest")
@RouteConfig(group = "test")
@RouteConfig(action = "com.fss.hello")
public class DetailActivity extends AppCompatActivity {
...
}
如果不是使用的Java8
@RouteConfigContainer(
value = {
@RouteConfig(name = "routeTest"),
@RouteConfig(group = "test"),
@RouteConfig(action = "com.fss.hello")
}
)
public class DetailActivity extends AppCompatActivity {
...
}
8,我想查看Activity的返回值,有没有更好的方式?
我们只需要将withResultCallBack设为true即可
@RouteConfig(requestCode = 1234, withResultCallBack = true)
对应生成的DefaultRouteApi
int REQUEST_CODE_TO_DETAIL_ACTIVITY = 1234;
@Route(
activity = DetailActivity.class,
requestCode = REQUEST_CODE_TO_DETAIL_ACTIVITY
)
void routeToDetailActivity(Context formObj, OnActivityResult onActivityResult);
可以看到上面的方法多了一个OnActivityResult类型的参数
然后我们就可以这样使用:
FssRouteApi.DEFAULT_ROUTE_API.routeToDetailActivity(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);
}
}
总结上面的规律,我们会发现,我们想给某一个Activity添加跳转方式时,可以在对应的Activity上添加@RouteConfig注解,然后根据我们的需求给不同的参数,然后编译器在编译时会自动为我们生成相应的接口文件,我们便可以在代码里使用了。
但是,其实我们也可以不使用@RouteConfig注解,直接写相应的接口文件
我们先在项目里添加一个MainRouteApi的接口,文件名及目录包名可以任意。
@RouteApi
public interface MainRouteApi {
@Route(activity = DetailActivity.class)
void routeDetail(Context fromObj);
@Route(action = "com.gongbo.detail")
Intent getRouteDetailIntent(Context fromObj);
@Route(action = "com.gongbo.detail", requestCode = REQUEST_CODE_DETAIL)
void routeDetailWithResult(Context fromObj, OnActivityResult onActivityResult);
@Route(action = Intent.ACTION_VIEW)
void routeToView(Context fromObj, Uri data);
}
但是,我们需要注意几个地方
1,每一个方法第一个参数必须是Context类型。
2,接口必须有@RouteApi注解。
接下来,我们还有个问题需要讨论下,那就是@RouteApi是做什么的?为什么我们自定义的接口是MainRouteApi,而使用时确实这样调用的
FssRouteApi.MAIN_ROUTE_API.routeToDetailActivity(this);
其实,这两个问题是同一个问题。我们看下FssRouteApi是什么。
public class FssRouteApi {
public static final MainRouteApi MAIN_ROUTE_API;
static {
MAIN_ROUTE_API = FssRouter.createRouteApi(MainRouteApi.class);
}
}
其实,FssRouteApi里有一个我们自定义接口的常量且已经为我们初始化过了,这个常量内部使用了动态代理的方式实现跳转页面逻辑的处理,我们这里就不讨论了。如果我们不在MainRouteApi接口添加@RouteApi注解,我们会发现要么是编译器不会生成FssRouteApi文件,或者FssRouteApi文件里没有刚刚的MAIN_ROUTE_API常量。所以我们自定义的接口文件必须加上@RouteApi注解。
更多FSS框架:
- Android开发利器-FSS开源框架之fss_common
- Android开发利器-FSS开源框架之方法运行优先级
- Android开发利器-FSS开源框架之绑定
- Android开发利器-FSS开源框架之ListView,RecyclerView适配器
如果想要了解fss框架的具体使用,我为大家提供了demo工程