本文主要说一个好用强大的Android路由框架–Rudolph

【推荐】好用强大的Android路由框架–Rudolph

Rudolph Android Router Framework(鲁道夫安卓路由框架组件)github上查看

目录

1.框架特性

  • 支持组件API模块自动生成
  • 自动生成路由Builder类与服务类的接口层;
  • 加载更快,更稳定,无需dex扫描方式加载;
  • 无需指定模块名,接入更简单;
  • 显式跳转与URL路由地址跳转融为一体,更方便快捷;
  • 通过Builder方式传参,无需手动写参数名,从而减少参数传错和修改带来的Bug隐患;
  • 支持所有Intent的参数类型;
  • 支持Activity 、Fragment、Service、Method四种路由类型
  • 支持Instant Run
  • 支持AndroidX
  • 支持Kotlin

2.依赖方式

Build.gradle

1
2
3
4
repositories {
jcenter()
...
}

Java:

1
2
3
4
dependencies {
implementation 'cn.wzbos.rudolph:rudolph:1.0.1'
annotationProcessor 'cn.wzbos.rudolph:rudolph-compiler:1.0.1'
}

Kotlin:

1
2
3
4
5
6
7
8
9
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'

...

dependencies {
implementation 'cn.wzbos.rudolph:rudolph:1.0.1'
kapt 'cn.wzbos.rudolph:rudolph-compiler:1.0.1'
}

3.代码混淆

如果开启了代码混淆,只需要在混淆配置文件中添加如下配置

1
2
3
4
5
-keep class * implements cn.wzbos.android.rudolph.IRouteTable{*;}
-keep class * implements cn.wzbos.android.rudolph.IRouteBinder{*;}
-keepclassmembers class ** {
@cn.wzbos.android.rudolph.annotations.Route <methods>;
}

4.调用方式

Activity

定义一个Activity路由,如果不需要用url方式调用可以不写路由地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Route("/activity/test")
public class TestActivity extends AppCompatActivity {
@Arg("userId")
int userId;

@Arg("userName")
String userName;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Rudolph.bind(this);
}

}

调用Activity

1
UserActivityRouter.builder().userId(11).userName("John").build().start(context);

或者

1
Rudolph.builder("/user?userId=11&userName=John").build().open(context);

Fragment

创建一个Fragment路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Route("/fragment/test")
public class TestFragment extends Fragment {
@Arg("userId")
int userId;

@Arg("userName")
String userName;

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Rudolph.bind(this);
}
}

调用Fragment

1
Fragment fragment = TestFragmentRouter.builder().userId(11).userName("John").build().open();

或者

1
Rudolph.builder("/fragment/user?userId=11&userName=John").build().open();

Service

创建一个服务(适用于跨module调用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Route(vaule="/service/test",export = true)
public class TestService implements IRouteService{

@Arg
int userId;

@Arg
String userName;

@Override
public void init(Bundle bundle) {
Log.d("TestService", "afterInject");
rudolph.bind(TestService.this, bundle);
}

@Export
public void showMessage(Context context, String msg) {
Toast.makeText(context, msg + "\nuserId:" + userId + ",userName:" + userName, Toast.LENGTH_SHORT).show();
}
}

注意:服务类必须实现IRouteService接口

调用服务

1
2
ITestService service = TestServiceRouter.builder().userId(1).userName("Tom").build().open();
service.showMessage(MainActivity.this, "Hello Provider!");

或者

1
2
ITestService service = (ITestService)Rudolph.builder("/service/test?userId=11&userName=John").build().open();
service.showMessage(MainActivity.this, "Hello Provider!");

Method

1
2
3
4
5
6
public class TestMethod {
@Route("/method/test")
public static void Test(@Arg Context context, @Arg int userId, @Arg String userName) {
Toast.makeText(context, "Hello Method!\nuserId:" + userId + ",userName:" + userName, Toast.LENGTH_SHORT).show();
}
}

调用方式:

1
Rudolph.builder("/method/test?userId=11&userName=John").build().open(context);

注意:
1.方法必须为静态方法
2.context是获取open(context)传的上下文,如果调用的时候没context值则接收的值为ApplicationContext

5.注解说明

@Route

此注解为标识一个路由;

  • 参数:
    • value:路由地址,可为空,例如@Route(“/room”)
    • export:是否导出API,一般组件化刚才才会用
1
2
3
@Route(value = "/user",export = true)
public class UserActivity extends AppCompatActivity {
}

@Arg

此注解为标识路由的参数(注意如果注解到字段上,此字段不能为private)。

  • 参数:
    • value:路由地址,可为空(默认取字段名),例如@Arg(“userId”),@Arg(RAW_URI)
    • base64:标识此参数是否为base64方式编码
    • json:标识此参数是否为json格式
1
2
3
4
5
6
7
8
9
@Route(value = "/user",export = true)
public class UserActivity extends AppCompatActivity {
@Arg("userId")
int userId;
@Arg
String userName;
@Arg(value="userInfo",base64=true, json=true)
String userInfo;
}

@Component

此注解为组件化所需要的注解,主要为提供组件初始化操作;

  • 参数:无
1
2
3
4
5
6
7
8
@Component
public class TestComponent implements IRouteTable {

@Override
public void init(Application application) {
Toast.makeText(application.getApplicationContext(), "组件xxx初始化啦!", Toast.LENGTH_SHORT).show();
}
}

@Export

导出注解的方法,此注解只能用在Method上,且此方法必须为非静态(static)的Public方法;

  • 参数:无
1
2
3
4
5
6
7
8
@Route
public class TestService implements IRouteService{

@Export
public void showMessage(String message) {

}
}

6.组件化

场景:A模块需要调用B模块

实现方式:需要导出B模块的API(当然如果想用纯URL的方式调用可以不导出),然后A、B 模块都依赖B模块的API

操作步骤:

第一步:在B模块的的build.gradle中增加如下配置,其中export_api_name为导出的API模块名,export_api_package为导出的API包名

1
2
3
4
5
6
7
8
9
10
11
12
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [
export_api_name : project.getName() + "_api",
export_api_package: "com.xxxx.module_b_api"
]
includeCompileClasspath = true
}
}
}

第二步:点击重新编译,然后就能看到生成的API工程,看到API工程后再到settings.gradle中增加以下依赖

1
include ':module_b_api'

第三步:需要在A模块B模块中增加依赖

1
2
3
dependencies {
implementation project(':module_b_api')
}

初始化组件

通过以下代码可以初始化每个组件

1
2
3
4
5
6
7
8
9

@Component
public class TestComponent implements IRouteTable {

@Override
public void init(Application application) {
Toast.makeText(application.getApplicationContext(), "组件xxx初始化啦!", Toast.LENGTH_SHORT).show();
}
}

(注意:@Component注解的类,每个module中只能存在一个)

7.常见问题

路由参数支持的数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
@Route(value = "/activity/test",export = true)
public class TestActivity extends AppCompatActivity {
@Arg(RAW_URI)
String routeUri;

@Arg("stringArg")
String stringArg;

@Arg(value = "string64", base64 = true)
String string64Arg;

@Arg("stringArray")
String[] stringArrayArg;


@Arg("boolArg")
boolean boolArg;

@Arg("booleanArray")
boolean[] booleanArrayArg;

@Arg("byteArg")
byte byteArg;

@Arg("byteArray")
byte[] byteArrayArg;

@Arg("shortArg")
short shortArg;

@Arg("shortArray")
short[] shortArrayArg;

@Arg("intArg")
int intArg;

@Arg("intArrayArg")
int[] intArrayArg;

@Arg("longArg")
long longArg;

@Arg("longArray")
long[] longArrayArg;

@Arg("charArg")
char charArg;

@Arg("charArray")
char[] charArrayArg;

@Arg("floatArg")
float floatArg;

@Arg("floatArray")
float[] floatArrayArg;

@Arg("doubleArg")
double doubleArg;

@Arg("doubleArray")
double[] doubleArrayArg;

@Arg("characterArg")
Character characterArg;

//ArrayList
@Arg
ArrayList<String> stringArrayListArg;

@Arg
ArrayList<Integer> integerArrayListArg;

@Arg(value = "charSequenceArrayList")
ArrayList<CharSequence> charSequenceArrayListArg;

@Arg(value = "parcelableArrayList")
ArrayList<Broker> parcelableArrayListArg;

@Arg(value = "serialized")
Broker serializedParam;

//json
@Arg(value = "json", json = true)
User<Broker> jsonParam;

//encode:json->base64,decode:base64->json
@Arg(value = "base64json", json = true, base64 = true)
User<Broker> base64jsonParam;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Rudolph.bind(this);
}
}

github上查看