原文地址 juejin.cn
前面两篇文章分别介绍了 Android 组件化基础知识以及 Android 组件化过程
Application 的相关知识,在阅读本文之前可以先阅读下面两篇文章:
Android 组件化过程中涉及到不同 module
之间界面的跳转也是分厂重要的,如果要对自己经手的项目进行组件化改造,ARouter
是一个非常容易上手的路由框架,由大厂开发团队维护,相信质量是没有问题的。
ARouter 是 albaba 团队开源的一个 Android App
组件化改造的一个框架,支持模块之间的路由、通信、拦截功能,相比原生跳转来说更能适应组件化开发,本文主要通过实例总结一下
Arouter 的常用功能,具体如下:
ARouter 的配置
应用内跳转
应用内携带参数跳转
Activity 返回结果处理
通过 Uri 跳转及参数解析
Module 之间的跳转
服务调用
显示效果
ARouter 的配置
在对应的 build.gradle 文件中配置 ARouter 的相关依赖如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 android { defaultConfig { ... javaCompileOptions { annotationProcessorOptions { arguments = [AROUTER_MODULE_NAME: project .getName()] } } } } dependencies { compile 'com.alibaba:arouter-api:1.5.2' annotationProcessor 'com.alibaba:arouter-compiler:1.5.2' ... }
可以选择配置路由表自动加载,在项目下面的 build.gradle
文件中进行配置,配置方式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 apply plugin: 'com.alibaba.arouter' buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.0.1' classpath "com.alibaba:arouter-register:1.0.2" } }
此外,还需在 Application 中初始化 ARouter,如下:
1 2 3 4 5 6 7 8 9 10 11 12 @Override public void onCreate () { super .onCreate(); if (BuildConfig.DEBUG){ ARouter.openLog(); ARouter.openDebug(); } ARouter.init(this ); }
ARouter应用内跳转
使用 ARouter 进行应用内跳转非常简单,只需要在要跳转的 Activity 上添加
@Route 注解即可,具体如下:
1 2 3 4 5 6 7 8 9 10 11 12 @Route(path = FirstActivity.PATH) public class FirstActivity extends AppCompatActivity { public static final String PATH = "/test/firstActivity" ; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_first); } }
然后使用 ARouter
提供的跳转方式来进行应用内部之间的跳转,具体如下:
1 2 3 4 ARouter.getInstance() .build(FirstActivity.PATH) .navigation();
应用内携带参数跳转
ARouter 通过 withString 等一系列 with
开头的方法设置与之对应的参数来进行参数传递,具体如下:
1 2 3 4 5 ARouter.getInstance() .build(SecondActivity.PATH) .withString(SecondActivity.PARAM, "这是跳转携带的参数" ) .navigation();
然后使用 Intent 在跳转到的 Activity 中使用 Intent
获取传递过来的参数,具体如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Route(path = SecondActivity.PATH) public class SecondActivity extends AppCompatActivity { public static final String PATH = "/test/secondActivity" ; public static final String PARAM = "param" ; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_second); Intent intent = getIntent(); if (intent!=null ){ String param = intent.getStringExtra(PARAM); Toast.makeText(this , param, Toast.LENGTH_SHORT).show(); } } }
Activity 返回结果处理
Activity 返回结果处理和原生几乎一致,即在跳转时携带
requestCode,具体如下:
1 2 3 4 ARouter.getInstance() .build(ThreeActivity.PATH) .navigation(this , 100 );
然后,在 Activity 返回的时候使用 Intent 携带参数 setResult
即可,具体如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Route(path = ThreeActivity.PATH) public class ThreeActivity extends AppCompatActivity { public static final String PATH = "/test/threeActivity" ; public static final String PARAM_RESULT = "param_result" ; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_three); Intent intent = getIntent(); intent.putExtra(PARAM_RESULT,"这是返回携带的参数" ); setResult(RESULT_OK,intent); } }
通过 Uri 跳转及参数解析
ARouter 还支持通过 Uri 进行跳转,首先创建一个无界面的 Activity
用于监听 Scheme 事件,由该 Activity 进行统一转发 Uri,所有的 Uri
都要通过这里然后进行分发跳转,可以很好的进行 Uri
的控制,一定程度上提高了使用 Uri 跳转的安全性,实行一个无界面的 Activiry
如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class SchemeFilterActivity extends AppCompatActivity { @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); Uri uri = getIntent().getData(); ARouter.getInstance().build(uri).navigation(this , new NavCallback () { @Override public void onArrival (Postcard postcard) { finish(); } }); } }
在 AndroidManifest 文件中配置 host、scheme 以及
Action,具体如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 <activity android:> <intent-filter> <data android:host="test.manu.com" android:scheme="arouter" /> <action android: /> <action android: /> <category android: /> <category android: /> </intent-filter> </activity>
然后,在 assets 文件夹中创建一个 html 文件,通过点击跳转链接完成 Uri
的跳转,html 内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" > <title></title> </head> <body> <h2>跳转测试</h2> <h2>自定义Scheme</h2> <p> <!--不带参数--> <a href="arouter://test.manu.com/test/fiveActivity" >arouter: </p> <p> <!--携带参数--> <a href="arouter://test.manu.com/test/sixActivity?>arouter://test111.manu.com/test/sixActivity?name=alex&age=18&score={" score":" 90 "," rank":" 2 "}</a> </p> </body> </html>
具体效果查看运行效果图。
然后,使用 WebView 加载该 Html,就可以跳转到对应的 Activity
了,也就是链接中的 fiveActivity 和 SixActivity,两个 Activity
分别如下:
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 @Route(path = FiveActivity.PATH) public class FiveActivity extends AppCompatActivity { public static final String PATH = "/test/fiveActivity" ; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_five); } } @Route(path = SixActivity.PATH) public class SixActivity extends AppCompatActivity { public static final String PATH = "/test/sixActivity" ; @Autowired public String name; @Autowired public int age; @Autowired public ScoreBean score; @BindView(R.id.tvData) TextView tvData; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_six); ButterKnife.bind(this ); ARouter.getInstance().inject(this ); String info = " + score; tvData.setText(info); Log.i(" SixActivity", info); } }
Module 之间的跳转
主 module 和子 module 和子 module 之间的跳转也非常容易,如主 module
跳转子 module,当然主 module 和子 module 都在配置 ARouter
才可以进行进行跳转,可在主 module 中创建一个接口管理要跳转的子 module
的路径,具体如下:
1 2 3 4 5 public interface Module { String MODULE_ONE = "/module1/module-one" ; String MODULE_TWO = "/module2/module-two" ; }
然后,直接进行跳转,具体如下:
1 2 3 4 ARouter.getInstance() .build(Module.MODULE_ONE) .navigation();
服务调用
ARouter 里面的服务调用不能和 Android 里面的 Service
相混淆,ARouter
的里面的服务调用实际上是对某个业务的封装 ,通过 ARouter
这一层的统一封装,使得调用起来更方便,只需知道路径和名称就可以随意调用,实现
IProvider 创建一个 Service 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Route(path = "/service/singleService") public class SingleService implements IProvider { public static final String PATH = "/service/singleService" ; private Context mContext; public void showMessage () { Toast.makeText(mContext, "这是对外提供的服务" , Toast.LENGTH_SHORT).show(); } @Override public void init (Context context) { this .mContext = context; Log.i("SingleService" , "SingleService has init" ); } }
然后就可以调用了,调用方式如下:
1 2 3 4 5 6 7 ARouter.getInstance().navigation(SingleService.class).showMessage(); ((SingleService) ARouter.getInstance() .build(SingleService.PATH) .navigation()) .showMessage();
此外,还可以使用依赖注入的方式完成服务的调用,这种方式便于多个服务进行管理,创建一个服务管理类如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class ServiceManage { @Autowired SingleService singleService; public ServiceManage () { ARouter.getInstance().inject(this ); } public void getService () { singleService.showMessage(); } }
然后通过服务管理类调用具体的服务如下:
1 2 3 ServiceManage manage = new ServiceManage ();manage.getService();