本文主要说一个好用强大的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中增加以下依赖
第三步:需要在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;
@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;
@Arg(value = "json", json = true) User<Broker> jsonParam;
@Arg(value = "base64json", json = true, base64 = true) User<Broker> base64jsonParam; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Rudolph.bind(this); } }
|
github上查看