Aouter的一款由Ali团队开发的Android路由框架,本文旨在讲解Arouter官方网站的Demo,而不是自己的Demo,因为我觉得官方的Demo已经足够满足开发的业务需求,就不必自己再轮一篇,本文是对文档的一些补充。
git clone https://github.com/alibaba/ARouter.git 神传送下载源码
我们先来闲聊下我们项目中可能用到的跳转业务功能:
1、Activity跳转,并传参数(参数包括基本类型和引用类型)
2、Fragment跳转,并传参数(参数包括基本类型和引用类型)
3、我想在跳转的时候做点判断和控制什么的,甚至是拦截一些界面不给没有权限的用户访问等需求
4、我想解耦,不依赖某个Activity的引用
以上四点基本满足我们对跳转的需求,但是原生我们无法拦截界面的跳转,1、2点倒是可以实现,但是重复性劳动非常大,而且显示跳转的时候,依赖跳转之后的Activity.class ,这使得我们在并行开发的时候非常被动,如果使用隐式跳转,当Activity不存在的时候又会崩溃,所以基于以上考虑,我不得不引入一个路由框架,进行对Aouter的进行调研后和阅读关键性源码后,决定使用这个框架进行开发。
提供下刘志龙大神对Arouter的架构和原理进行讲解概况地址,大家有兴致可以看下:
集成Aouter
Aouter Api包括三种类型:
api :com.alibaba:arouter-api:x.x.x
注解器:com.alibaba:arouter-compiler:x.x.x
自动注册插件:com.alibaba:arouter-register:x.x.x
(以目前最新版本为列)在app的build.gradle里面添加:
android { defaultConfig { ... javaCompileOptions { annotationProcessorOptions { arguments = [ moduleName : project.getName() ] } } } }
dependencies { // 替换成最新版本, 需要注意的是api // 要与compiler匹配使用,均使用最新版可以保证兼容 compile 'com.alibaba:arouter-api:1.3.1' annotationProcessor 'com.alibaba:arouter-compiler:1.1.4' }
如果AndroidStudio 3.0 gradle插件3.0 以上 compile 使用 api替换
如果gradle插件少于2.2的版本 annotationProcessor需要使用apt插件替换
如果是Kotlin项目,请使用k-apt插件替换
kotilin配置列子:
项目层的build.gradle,添加插件:
buildscript { ext.kotlin_version = '1.1.3-2' dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } }
app层的build.gradle:
apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-android-extensions'
dependencies { kapt 'com.alibaba:arouter-compiler:1.0.3' }
注:假如是组件化项目需要注意 javaCompileOptions和 annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'每个组件的配置都需要有 ,api可以放在基础库中。
配置自动注册插件,在项目层的build.gradle:
dependencies { classpath 'com.alibaba:arouter-register:1.0.2' }
版本api 1.3.1对应1.0.2 搞错了无效。
基础概念
注解:
1、@Route 路由注解。 定义一个可以找到某个目标的字符串,用于Activity、Fragment、Service的路径。
path:路径字符串 比如“test/activity1”
注意:path新版必须设置一个“XXX/XXX”斜杠的类型,因为一个斜杠之前的字符串作为一个组
group:组,新版本不建议使用
name:定义路径的名字,默认为 “undefined”。用来添加注释
priority:优先级 默认为-1。
extras :额外的数据,Interget类型,可以用来控制目标页面的业务逻辑,比如1 or 0表示某个页面是否展示,把他当前2禁止的时候可以控制32个业务开关。一般不常用。
2、@Interceptor 定义拦截器,添加该注释可以定义一个全局Activity跳转的拦截器。
priority:优先级
name:默认Default
3、@Autowired 注入参数,用于接收传送参数 或者 注入Service
name:参数名,默认""
required:是否必须,如果为true, 数据为null的话会导致app崩溃
desc:对参数进行描述 相当于注释
初始化
if (isDebug()) { // 这两行必须写在init之前,否则这些配置在init过程中将无效 ARouter.openLog(); // 打印日志 ARouter.openDebug(); // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险) } ARouter.init(mApplication); // 尽可能早,推荐在Application中初始化
Activity跳转
简单的Activity跳转:
使用Router定义路径
@Route(path = "/test/activity1") public class Test1Activity extends AppCompatActivity {
跳转
ARouter .getInstance() .build("/test/activity1").navigation();
带基础参数的Activity
跳转
ARouter.getInstance() .build("/test/activity2") .withString("key1", "value1") .navigation();
withXX (key,value)传送的是基本类型,可以通过key接收到这个数据
使用withObject(key,value)传送自定义对象,使用自定义对象要实现SerializationService接口,并且规定路由设置成@Route(path = "/service/json") 。比如使用FastJSON进行序列化:
@Route(path = "/service/json") public class JsonServiceImpl implements SerializationService { @Override public void init(Context context) { } @Override public <T> T json2Object(String text, Class<T> clazz) { return JSON.parseObject(text, clazz); } @Override public String object2Json(Object instance) { return JSON.toJSONString(instance); } }
Parcelable和Serializable对象传输是直接支持的。
接收数据的时候有两种方式
一种是原生使用的接收方式
String value = getIntent().getXXXExtra("key");
另一种是使用注释获取到,先在Activity中添加 ARouter.getInstance().inject(this);
@Autowired(name="key") String key;
通过name来匹配,默认通过类型匹配。
需要返回的Activity跳转
ARouter.getInstance() .build("/test/activity2") .navigation(this, 666);
setResult(666);
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case 666: Log.e("activityResult", String.valueOf(resultCode)); break; default: break; } }
自定义协议跳转的Activity
定义协议:
<activity android:name=".SchemeFilterActivity"> <!-- Schame --> <intent-filter> <data android:host="m.aliyun.com" android:scheme="arouter"/> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> </activity>
其中scheme定义协议头,可以随便自己定制,m.aliun.com是host
当我们跳转的时候需要一个中间者进行调度,如:SchemeFilterActivity就是用来对协议进行中间调度的
public class SchemeFilterActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 直接通过ARouter处理外部Uri Uri uri = getIntent().getData(); ARouter.getInstance().build(uri).navigation(this, new NavCallback() { @Override public void onArrival(Postcard postcard) { finish(); } }); } }
我们想要跳转时,可以这样, 比如需要跳转到 test/activity2
Uri testUriMix = Uri.parse("arouter://m.aliyun.com/test/activity2"); ARouter.getInstance().build(testUriMix) .withString("key1", "value1") .navigation();
上面的SchemeFilterActivity只是一个中间调度,不是我们的目标Activity,我们的目标activity是 test/activity2,Uri需要这样拼接:协议字符串+目标跳转的路径。
当SchemeFilterActivity接收到uri后再进行一次跳转,从SchemeFilterActivity中取出来的getIntent().getData()==" test/activity2"。
我们还可以在网页直接跳转到应用内的activity,在SchemeFilterActivity清单文件中 intent-filter添加Links
<intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:host="m.aliyun.com" android:scheme="http"/> <data android:host="m.aliyun.com" android:scheme="https"/> </intent-filter>
html中使用标签<a></a>
<a href="arouter://m.aliyun.com/test/activity3?name=alex&age=18&boy=true&high=180">arouter://m.aliyun.com/test/activity3?name=alex&age=18&boy=true&high=180</a>后面?之后是传参数。相当于一个get请求一样。
跳转监听器回调NavCallback
ARouter.getInstance().build("/xxx/xxx").navigation(this, new NavCallback() { @Override public void onFound(Postcard postcard) { Log.d("ARouter", "找到了"); } @Override public void onLost(Postcard postcard) { Log.d("ARouter", "找不到了"); } @Override public void onArrival(Postcard postcard) { Log.d("ARouter", "跳转完了"); } @Override public void onInterrupt(Postcard postcard) { Log.d("ARouter", "被拦截了"); } });
使用NavCallback进行监听跳转过程中是否被拦截,或者是否完成跳转。比如我们可以在跳转后进行一些保存数据的操作,当没有发现Activity的时候提示模块未开放等功能。
转场动画
跳转动画在Arouter里面实现也很简单,只需要定义好出入的动画然后调用如下:
ARouter.getInstance() .build("/test/activity2") .withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom) .navigation(this);很多时候大家都会问,为什么设置了无效,这可能并不是Arouter的问题,而是因为你的样式为了不出现黑屏设置了 android:windowIsTranslucent为true导致的。
共享元素的转场动画
if (Build.VERSION.SDK_INT >= 16) { ActivityOptionsCompat compat = ActivityOptionsCompat. makeScaleUpAnimation(v, v.getWidth() / 2, v.getHeight() / 2, 0, 0); ARouter.getInstance() .build("/test/activity2") .withOptionsCompat(compat) .navigation(); } else { ARouter.getInstance() .build("/test/activity2") .navigation(); }因为只有API大于16才支持共享元素,所以当少于16的时候我们直接跳转。
获取Fragment
添加路由:
@Route(path = "/test/fragment") public class BlankFragment extends Fragment
带参数的跳转
未完待续。。。