Arouter入门篇

阅读: 评论:0

Arouter入门篇

Arouter入门篇

    Aouter的一款由Ali团队开发的Android路由框架,本文旨在讲解Arouter官方网站的Demo,而不是自己的Demo,因为我觉得官方的Demo已经足够满足开发的业务需求,就不必自己再轮一篇,本文是对文档的一些补充。

官方地址

git clone .git 神传送下载源码

我们先来闲聊下我们项目中可能用到的跳转业务功能:

1、Activity跳转,并传参数(参数包括基本类型和引用类型)

2、Fragment跳转,并传参数(参数包括基本类型和引用类型)

3、我想在跳转的时候做点判断和控制什么的,甚至是拦截一些界面不给没有权限的用户访问等需求

4、我想解耦,不依赖某个Activity的引用

        以上四点基本满足我们对跳转的需求,但是原生我们无法拦截界面的跳转,1、2点倒是可以实现,但是重复性劳动非常大,而且显示跳转的时候,依赖跳转之后的Activity.class ,这使得我们在并行开发的时候非常被动,如果使用隐式跳转,当Activity不存在的时候又会崩溃,所以基于以上考虑,我不得不引入一个路由框架,进行对Aouter的进行调研后和阅读关键性源码后,决定使用这个框架进行开发。

提供下刘志龙大神对Arouter的架构和原理进行讲解概况地址,大家有兴致可以看下:

点击打开链接  

集成Aouter

Aouter Api包括三种类型:

api :com.alibaba:

注解器:com.alibaba:

        自动注册插件:com.alibaba:

    (以目前最新版本为列)在app的adle里面添加:

    

android {defaultConfig {...javaCompileOptions {annotationProcessorOptions {arguments = [ moduleName : Name() ]}}}
}
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配置列子:

项目层的adle,添加插件:

buildscript {ext.kotlin_version = '1.1.3-2'dependencies {classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"}
}

app层的adle:

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可以放在基础库中。

配置自动注册插件,在项目层的adle:

  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

    跳转

 Instance().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 {@Overridepublic void init(Context context) {}@Overridepublic <T> T json2Object(String text, Class<T> clazz) {return JSON.parseObject(text, clazz);}@Overridepublic String object2Json(Object instance) {JSONString(instance);}
}

    Parcelable和Serializable对象传输是直接支持的。

    

    接收数据的时候有两种方式

    一种是原生使用的接收方式

 String value = getIntent().getXXXExtra("key");

    另一种是使用注释获取到,先在Activity中添加

@Autowired(name="key")
String key;

    通过name来匹配,默认通过类型匹配。

   需要返回的Activity跳转

    

Instance().build("/test/activity2").navigation(this, 666);
setResult(666);
 @Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {ActivityResult(requestCode, resultCode, data);switch (requestCode) {case 666:Log.e("activityResult", String.valueOf(resultCode));break;default:break;}}

 自定义协议跳转的Activity

    定义协议:

<activity android:name=".SchemeFilterActivity"><!-- Schame --><intent-filter><dataandroid:host="m.aliyun"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是host

 当我们跳转的时候需要一个中间者进行调度,如:SchemeFilterActivity就是用来对协议进行中间调度的

public class SchemeFilterActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {Create(savedInstanceState);//        直接通过ARouter处理外部UriUri uri = getIntent().getData();Instance().build(uri).navigation(this, new NavCallback() {@Overridepublic void onArrival(Postcard postcard) {finish();}});}
}

我们想要跳转时,可以这样, 比如需要跳转到 test/activity2

 Uri testUriMix = Uri.parse("arouter://m.aliyun/test/activity2");Instance().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"/><dataandroid:host="m.aliyun"android:scheme="http"/><dataandroid:host="m.aliyun"android:scheme="https"/></intent-filter>

html中使用标签<a></a>

<a href="arouter://m.aliyun/test/activity3?name=alex&age=18&boy=true&high=180">arouter://m.aliyun/test/activity3?name=alex&age=18&boy=true&high=180</a>
后面?之后是传参数。相当于一个get请求一样。

跳转监听器回调NavCallback

    

 Instance().build("/xxx/xxx").navigation(this, new NavCallback() {@Overridepublic void onFound(Postcard postcard) {Log.d("ARouter", "找到了");}@Overridepublic void onLost(Postcard postcard) {Log.d("ARouter", "找不到了");}@Overridepublic void onArrival(Postcard postcard) {Log.d("ARouter", "跳转完了");}@Overridepublic void onInterrupt(Postcard postcard) {Log.d("ARouter", "被拦截了");}});

使用NavCallback进行监听跳转过程中是否被拦截,或者是否完成跳转。比如我们可以在跳转后进行一些保存数据的操作,当没有发现Activity的时候提示模块未开放等功能。

转场动画

跳转动画在Arouter里面实现也很简单,只需要定义好出入的动画然后调用如下:

Instance().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);Instance().build("/test/activity2").withOptionsCompat(compat).navigation();} else {Instance().build("/test/activity2").navigation();}

因为只有API大于16才支持共享元素,所以当少于16的时候我们直接跳转。

指定Flag

如果跳转的时候我们不设置Activity,比如&#Instance().build("/xxx/xxx").navigation();

那么默认的Flag就是:Intent.FLAG_ACTIVITY_NEW_TASK,Intent.FLAG_ACTIVITY_NEW_TASK类型launchMode="SingleTask"这是非常影响性能的操作,所以不建议这些写.

还有一种就是不设置,使用的是注册清单里面的luanchMode.

如果想要指定Flag,如下:

Instance().build("").withFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP).navigation(this);
其中Flags值是有限制的,具体查阅@ FlagInt

获取Fragment

添加路由:

@Route(path = "/test/fragment")
public class BlankFragment extends Fragment

带参数的跳转

 Fragment fragment = (Fragment) Instance().build("/test/fragment").withString("key","关键词").withObject("obj",testObj1).navigation();

在Fragment中接收,先添加


    

 public BlankFragment() {Instance().inject(this);}

使用注释接收参数:

@Autowired(name = "key",desc = "名称")
String name;@Autowired(required = true,name = "obj",desc = "一个测试对象")
TestObj obj;

name代表 键值对的key,required设置为true不能为null否则会崩溃,desc是一段对字段的描述。

使用拦截器

    当我们需要对页面跳转进行拦截时,我们可以使用Arouter内置的拦截进行处理,比如常见的场景有:判断页面是否需要登录状态,未登录跳转到登录页面登录。

    比如:我们需要拦截“/test/activity4”页面,如果是就提示需要登录:

@Interceptor(priority = 7,name = "aasj")
public class Test1Interceptor implements IInterceptor {Context mContext;/**拦截进行一些操作后 决定是否放行*/@Overridepublic void process(final Postcard postcard, final InterceptorCallback callback) {if ("/test/activity4".Path())) {MainLooper.runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(mContext,"您需要进行登录才能使用该功能",Toast.LENGTH_SHORT).show();}});} else {Continue(postcard);}}/*** 初始化*/@Overridepublic void init(Context context) {mContext = context;Log.e("testService", Name() + " has init.");}
}

其中priority决定优先级,一个优先级对应一个拦截器,拦截器是对所有Actvity都有效的,除非你在内部通过path剔除。通过

注意:process方法内部不是主线程。

当我们不希望拦截器拦截到我们,还可以设置绿色通道:

// 使用绿色通道(跳过所有的拦截器)
Instance().build("/home/main").greenChannel().navigation();

使用Arouter内置的服务

什么情况下我们会使用到服务呢?

目前市面上比较流行,组件化,组件化的要求就是热拔插,能随时分离各个APP的业务和分开打包,所以有时候我们需要执行一些功能的时候,可以需要调用另外一个组件的数据,就是通过Service来进行解耦的。

比如ModuleA 提供一个HelloService,HelloService输出一个Toast,ModuleB就可以从内置的Router容器中获取到HelloService来进行调用方法,输出Toast.

服务的声明:

服务应该先定义一个HelloService接口,这个接口需要放置在ModuleA和ModuleB都能引用到的父Lib中,然后Module实现HelloService接口:

public interface HelloService extends IProvider {void sayHello(String name);
}

Service必须继承IProvider

@Route(path = "/service/single")
public class SingleService implements IProvider {Context mContext;public void sayHello(String name) {Toast.makeText(mContext, "Hello " + name, Toast.LENGTH_SHORT).show();}@Overridepublic void init(Context context) {mContext = context;}
}

Service也需要定义路由,以便框架能够查找到。

我们可以使用三种方式获取到Service:

1、依赖注入  、

    @Autowired

    HelloService helloService;

2、根据HelloService .class类型获取

    helloService&#Instance().navigation(HelloService.class);

类型查找只能实现单一的服务的时候才能用,多实现服务还是得用依赖注入和根据路径查找的方法。

3、根据路径查找

helloService = (HelloService) Instance().build("service/hello").navigation(); 

服务还有Aouter内部的一些服务,比如PathReplaceService用来替换路径,SerializationService用来序列化对象,InterceptorServiceImpl用来处理拦截器的执行等服务,我们将在源码篇进行解读。

混淆规则

-keep public class com.alibaba.utes.**{*;}
-keep class * implements com.alibaba.android.plate.ISyringe{*;}# 如果使用了 byType 的方式获取 Service,需添加下面规则,保护接口
-keep interface * implements com.alibaba.android.plate.IProvider# 如果使用了 单类注入,即不定义接口实现 IProvider,需添加下面规则,保护实现
-keep class * implements com.alibaba.android.plate.IProvider

本文发布于:2024-01-29 19:45:38,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170652874417841.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:入门篇   Arouter
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23