[Alibaba-ARouter] 简单好用的Android页面路由框架
开发一款App,总会遇到各种各样的需求和业务,这时候选择一个简单好用的轮子,就可以事半功倍
前言
Intent intent = new Intent(mContext, XxxActivity.class);
intent.putExtra("key","value");
startActivity(intent); Intent intent = new Intent(mContext, XxxActivity.class);
intent.putExtra("key","value");
startActivityForResult(intent, );
上面一段代码,在Android开发中,最常见也是最常用的功能就是页面的跳转,我们经常需要面对从浏览器或者其他App跳转到自己App中页面的需求,不过就算是简简单单的页面跳转,随着时间的推移,也会遇到一些问题:
- 集中式的URL管理:谈到集中式的管理,总是比较蛋疼,多人协同开发的时候,大家都去
AndroidManifest.xml
中定义各种IntentFilter
,使用隐式Intent,最终发现AndroidManifest.xml
中充斥着各种Schame,各种Path,需要经常解决Path重叠覆盖、过多的Activity被导出,引发安全风险等问题 - 可配置性较差:Manifest限制于xml格式,书写麻烦,配置复杂,可以自定义的东西也较少
- 跳转过程中无法插手:直接通过Intent的方式跳转,跳转过程开发者无法干预,一些面向切面的事情难以实施,比方说登录、埋点这种非常通用的逻辑,在每个子页面中判断又很不合理,毕竟activity已经实例化了
- 跨模块无法显式依赖:在App小有规模的时候,我们会对App做水平拆分,按照业务拆分成多个子模块,之间完全解耦,通过打包流程控制App功能,这样方便应对大团队多人协作,互相逻辑不干扰,这时候只能依赖隐式Intent跳转,书写麻烦,成功与否难以控制。
另一个轮子
为了解决以上问题,我们需要一款能够解耦、简单、功能多、定制性较强、支持拦截逻辑的路由组件:我们选择了Alibaba的ARouter,偷个懒,直接贴ARouter的中文介绍文档:
一、功能介绍
- 支持直接解析URL进行跳转、参数按类型解析到Bundle,支持Java基本类型(*)
- 支持应用内的标准页面跳转,API接近Android原生接口
- 支持多模块工程中使用,允许分别打包,包结构符合Android包规范即可(*)
- 支持跳转过程中插入自定义拦截逻辑,自定义拦截顺序(*)
- 支持服务托管,通过ByName,ByType两种方式获取服务实例,方便面向接口开发与跨模块调用解耦(*)
- 映射关系按组分类、多级管理,按需初始化,减少内存占用提高查询效率(*)
- 支持用户指定全局降级策略
- 支持获取单次跳转结果
- 丰富的API和可定制性
- 被ARouter管理的页面、拦截器、服务均无需主动注册到ARouter,被动发现
- 支持Android N推出的Jack编译链
二、不支持的功能
- 自定义URL解析规则(考虑支持)
- 不能动态加载代码模块和添加路由规则(考虑支持)
- 多路径支持(不想支持,貌似是导致各种混乱的起因)
- 生成映射关系文档(考虑支持)
三、典型应用场景
- 从外部URL映射到内部页面,以及参数传递与解析
- 跨模块页面跳转,模块间解耦
- 拦截跳转过程,处理登陆、埋点等逻辑
- 跨模块API调用,模块间解耦(注册ARouter服务的形式,通过接口互相调用)
四、基础功能
添加依赖和配置
apply plugin: 'com.neenbedankt.android-apt'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
} apt {
arguments {
moduleName project.getName();
}
} dependencies {
apt 'com.alibaba:arouter-compiler:x.x.x'
compile 'com.alibaba:arouter-api:x.x.x'
...
}
添加注解
// 在支持路由的页面、服务上添加注解(必选)
// 这是最小化配置,后面有详细配置
@Route(path = "/test/1")
public class YourActivity extend Activity {
...
}
初始化SDK
ARouter.init(mApplication); // 尽可能早,推荐在Application中初始化
发起路由操作
// 1. 应用内简单的跳转(通过URL跳转在'中阶使用'中)
ARouter.getInstance().build("/test/1").navigation(); // 2. 跳转并携带参数
ARouter.getInstance().build("/test/1")
.withLong("key1", 666L)
.withString("key3", "")
.navigation();
添加混淆规则(如果使用了Proguard)
-keep public class com.alibaba.android.arouter.routes.**{*;}
五、进阶用法
通过URL跳转
// 新建一个Activity用于监听Schame事件
// 监听到Schame事件之后直接传递给ARouter即可
// 也可以做一些自定义玩法,比方说改改URL之类的
// http://www.example.com/test/1
public class SchameFilterActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // 外面用户点击的URL
Uri uri = getIntent().getData();
// 直接传递给ARouter即可
ARouter.getInstance().build(uri).navigation();
finish();
}
} // AndroidManifest.xml 中 的参考配置
<activity android:name=".activity.SchameFilterActivity">
<!-- 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"/>
</intent-filter> <!-- App 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>
</activity>
使用ARouter协助解析参数类型
// URL中的参数会默认以String的形式保存在Bundle中
// 如果希望ARouter协助解析参数(按照不同类型保存进Bundle中)
// 只需要在需要解析的参数上添加 @Param 注解
@Route(path = "/test/1")
public class Test1Activity extends Activity {
@Param // 声明之后,ARouter会从URL中解析对应名字的参数,并按照类型存入Bundle
public String name;
@Param
private int age;
@Param(name = "girl") // 可以通过name来映射URL中的不同参数
private boolean boy; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); name = getIntent().getStringExtra("name");
age = getIntent().getIntExtra("age", -);
boy = getIntent().getBooleanExtra("girl", false); // 注意:使用映射之后,要从Girl中获取,而不是boy
}
}
开启ARouter参数自动注入(实验性功能,不建议使用,正在开发保护策略)
// 首先在Application中重写 attachBaseContext方法,并加入ARouter.attachBaseContext();
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base); ARouter.attachBaseContext();
} // 设置ARouter的时候,开启自动注入
ARouter.enableAutoInject(); // 至此,Activity中的属性,将会由ARouter自动注入,无需 getIntent().getStringExtra("xxx")等等
声明拦截器(拦截跳转过程,面向切面搞事情)
// 比较经典的应用就是在跳转过程中处理登陆事件,这样就不需要在目标页重复做登陆检查 // 拦截器会在跳转之间执行,多个拦截器会按优先级顺序依次执行
@Interceptor(priority = , name = "测试用拦截器")
public class TestInterceptor implements IInterceptor {
/**
* The operation of this interceptor.
*
* @param postcard meta
* @param callback cb
*/
@Override
public void process(Postcard postcard, InterceptorCallback callback) {
... callback.onContinue(postcard); // 处理完成,交还控制权
// callback.onInterrupt(new RuntimeException("我觉得有点异常")); // 觉得有问题,中断路由流程 // 以上两种至少需要调用其中一种,否则会超时跳过
} /**
* Do your init work in this method, it well be call when processor has been load.
*
* @param context ctx
*/
@Override
public void init(Context context) { }
}
处理跳转结果
// 通过两个参数的navigation方法,可以获取单次跳转的结果
ARouter.getInstance().build("/test/1").navigation(this, new NavigationCallback() {
@Override
public void onFound(Postcard postcard) {
...
} @Override
public void onLost(Postcard postcard) {
...
}
});
自定义全局降级策略
// 实现DegradeService接口,并加上一个Path内容任意的注解即可
@Route(path = "/xxx/xxx") // 必须标明注解
public class DegradeServiceImpl implements DegradeService {
/**
* Router has lost.
*
* @param postcard meta
*/
@Override
public void onLost(Context context, Postcard postcard) {
// do something.
} /**
* Do your init work in this method, it well be call when processor has been load.
*
* @param context ctx
*/
@Override
public void init(Context context) { }
}
为目标页面声明更多信息
// 我们经常需要在目标页面中配置一些属性,比方说"是否需要登陆"之类的
// 可以通过 Route 注解中的 extras 属性进行扩展,这个属性是一个 int值,换句话说,单个int有4字节,也就是32位,可以配置32个开关
// 剩下的可以自行发挥,通过字节操作可以标识32个开关
@Route(path = "/test/1", extras = Consts.XXXX)
使用ARouter管理服务(一) 暴露服务
/**
* 声明接口
*/
public interface IService extends IProvider {
String hello(String name);
} /**
* 实现接口
*/
@Route(path = "/service/1", name = "测试服务")
public class ServiceImpl implements IService { @Override
public String hello(String name) {
return "hello, " + name;
} /**
* Do your init work in this method, it well be call when processor has been load.
*
* @param context ctx
*/
@Override
public void init(Context context) { }
}
使用ARouter管理服务(二) 发现服务
. 可以通过两种API来获取Service,分别是ByName、ByType
IService service = ARouter.getInstance().navigation(IService.class); // ByType
IService service = (IService) ARouter.getInstance().build("/service/1").navigation(); // ByName service.hello("zz"); . 注意:推荐使用ByName方式获取Service,ByType这种方式写起来比较方便,但如果存在多实现的情况时,SDK不保证能获取到你想要的实现
使用ARouter管理服务(三) 管理依赖
可以通过ARouter service包装您的业务逻辑或者sdk,在service的init方法中初始化您的sdk,不同的sdk使用ARouter的service进行调用,
每一个service在第一次使用的时候会被初始化,即调用init方法。
这样就可以告别各种乱七八糟的依赖关系的梳理,只要能调用到这个service,那么这个service中所包含的sdk等就已经被初始化过了,完全不需要
关心各个sdk的初始化顺序。
六、更多功能
初始化中的其他设置
ARouter.openLog(); // 开启日志
ARouter.printStackTrace(); // 打印日志的时候打印线程堆栈
详细的API说明
// 构建标准的路由请求
ARouter.getInstance().build("/home/main").navigation(); // 构建标准的路由请求,并指定分组
ARouter.getInstance().build("/home/main", "ap").navigation(); // 构建标准的路由请求,通过Uri直接解析
Uri uri;
ARouter.getInstance().build(uri).navigation(); // 构建标准的路由请求,startActivityForResult
// navigation的第一个参数必须是Activity,第二个参数则是RequestCode
ARouter.getInstance().build("/home/main", "ap").navigation(this, ); // 直接传递Bundle
Bundle params = new Bundle();
ARouter.getInstance()
.build("/home/main")
.with(params)
.navigation(); // 指定Flag
ARouter.getInstance()
.build("/home/main")
.withFlags();
.navigation(); // 觉得接口不够多,可以直接拿出Bundle赋值
ARouter.getInstance()
.build("/home/main")
.getExtra(); // 使用绿色通道(跳过所有的拦截器)
ARouter.getInstance().build("/home/main").greenChannal().navigation();
aa
附录
最新版本
arouter-annotation : 1.0.0
arouter-compiler : 1.0.1
arouter-api : 1.0.2Gradle依赖
dependencies {
apt 'com.alibaba:arouter-compiler:1.0.1'
compile 'com.alibaba:arouter-api:1.0.2'
}
[Alibaba-ARouter] 简单好用的Android页面路由框架的更多相关文章
- WMRouter:美团外卖Android开源路由框架
WMRouter是一款Android路由框架,基于组件化的设计思路,功能灵活,使用也比较简单. WMRouter最初用于解决美团外卖C端App在业务演进过程中的实际问题,之后逐步推广到了美团其他App ...
- Android路由框架-ARouter详解
文章大纲 一.页面路由基本介绍1.什么是页面路由2.为什么要使用页面路由二.页面路由框架ARouter介绍1.常用功能介绍2.常见应用场景三.源码下载四.参考文章 一.页面路由基本介绍 1.什么是 ...
- Android 路由框架ARouter最佳实践
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/76165252 本文出自[赵彦军的博客] 一:什么是路由? 说简单点就是映射页面跳转 ...
- Android 页面跳转之生命周期调用顺序问题
Android Activity 常用技巧 Android Activity 启动模式和任务栈 Android 页面跳转之生命周期调用顺序问题 一.页面跳转逻辑分析 1.1 跳转逻辑分析 Androi ...
- 绿色简单的学校登录html页面
效果预览:http://hovertree.com/texiao/css/22/ 代码如下: <!DOCTYPE html> <html> <head> <m ...
- JavaScript学习笔记-简单的倒计时跳转页面
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
- HTTP lab01 做一个简单的测试用 web页面
做一个简单的测试用 web页面 1.安装httpd服务 yum install httpd 安装完httpd服务后,系统就自动生成了/var/www/html目录 创建一个 ...
- html5页面与android页面之间通过url传递参数
html5页面与android页面之间可以通过url传递参数,android将参数放在htm5的url ?后面,js获取url ?号后面的参数. 方法一: <scrīpt> /* 用途 ...
- 三行代码实现.NET MVC统计显示页面的执行时间 超简单的实现方法 分析页面执行效率
三行代码实现.NET MVC统计显示页面的执行时间 超简单的实现方法 分析页面执行效率 博客页脚处添加了页面执行时间统计显示,如下图所示,也可以直接查看网页页脚处. 实现方法非常简单,只需三行代 ...
随机推荐
- 第6章 令牌撤销端点(Token Revocation Endpoint) - IdentityModel 中文文档(v1.0.0)
OAuth 2.0令牌撤销的客户端库是作为扩展方法提供的HttpClient. 以下代码撤消撤销端点处的访问令牌令牌: var client = new HttpClient(); var resul ...
- 结合JDK源码看设计模式——适配器模式
定义: 将一个类的接口转换成客户期望的另外一个接口(重点理解适配的这两个字),使得接口不兼容的类可以一起工作适用场景: 已经存在的类,它的方法和需求不匹配的时候 在软件维护阶段考虑的设计模式 详解 首 ...
- [ArcGIS API for JavaScript 4.8] Sample Code-Get Started-MapView,SceneView简介
[官方文档:https://developers.arcgis.com/javascript/latest/sample-code/index.html] 一.Intro to MapView(2D ...
- Storm入门(十三)Storm Trident 教程
转自:http://blog.csdn.net/derekjiang/article/details/9126185 英文原址:https://github.com/nathanmarz/storm/ ...
- 转://IO的基础概念
磁盘IO.网络IO 对磁盘的每个IO就是在磁盘与一些RAM单元之间相互传送一些相邻的扇区的内容. 磁盘IO延时(IO Latency): 也称为IO响应时间,是指内核对磁盘发出一个 ...
- Demo更新列表
Sdk 对应的demo ESF (1)ESF/ESFramework.EntranceDemo.rar (2)ESF/4.ESFramework.Demos.Ftp.rar (3)ESF/6.ESFr ...
- eggjs 框架代理调试 SELF_SIGNED_CERT_IN_CHAIN 报错解决方案
eggjs 中的 this.ctx.curl 可以发起一个请求,配置 proxy 可以很方面的通过接口进行问题定位.代理方式如下: 1.开启 egg-development-proxyagent ,配 ...
- Nginx 相关介绍
Nginx的产生 没有听过Nginx?那么一定听过它的"同行"Apache吧!Nginx同Apache一样都是一种WEB服务器.基于REST架构风格,以统一资源描述符(Unifor ...
- python爬虫数据解析之BeautifulSoup
BeautifulSoup是一个可以从HTML或者XML文件中提取数据的python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式. BeautfulSoup是python爬虫三 ...
- “挑三拣四”地学一学Java I/O
古人云:“读书破万卷,下笔如有神”.也就是说,只有大量的阅读,写作的时候才能风生水起——写作意味着输出(我的知识传播给他人),而读书意味着输入(从他人的知识中汲取营养). 对于Java I/O来说,I ...