关于Android路由的实现
先说一下背景,目前有需求从外部包括其他应用和WEB跳转到我们自己的APP,就这么个简单的需求……
要实现这种外部跳转的功能,我们可以理解为打算跳转的一方有多少方式通知到APP进行相对的响应行为。所以,如果是应用之间的跳转,则有多种,你可以直接通过包名和具体的类名去打开已经exported=true的Activity,又或者直接通过Android的广播通知进行相关的APP,又或者通过自定义的URL去打开应用。但是如果涉及到Web打开外部应用的话,目前只有一种办法,那就是自定义应用的URL进行拦截,系统会自动调起相应的组件响应这个URL。
但是,要做这种需求,很少会仅仅是完成对外部的支持而已,通常也要进行一定的内部逻辑跳转映射。所以要做这种需求通常分为两个种,一种是对内的(应用内部自己的跳转逻辑),一种对外的(其他应用以及Web跳转逻辑)。
我们先说一下对外的情形,由于考虑到统一性,我们目前只有URL这种手段可以使用了。下面我们一一来说
1、对外跳转说明
1.1、关于URL的说明。
首先,我们得了解一下URL,这里直接引用 https://en.wikipedia.org/wiki/URL 的说明。为了方便说明,我稍稍修改一下,大概的格式如下:
scheme:[//host[:port]][/path][?query][#fragment]
首先,scheme是必须的,其他的都是不必须的,但是对于跳转来说,显然不可能,因为你要从这个url中取出跳转相关的信息。所以,通常一定要要有host和query。我们经常看到一些开源的路由实现,都会支持所谓的restful风格的url,比如:wytings://app/{city}/{id} ,但我个人认为是没有必要的。主要是因为这种外部跳转的行为,通常量比较少,其次应该尽量统一而且方便,而不是为了追求各种技术炫酷…我刻意看了微信的scheme就甚合我意~都是类似于这种格式:weixin://qrscan?a=1&b=2
我们进行一下归纳,就可以进行应用的URL定义了,首先scheme是必须项,看个人和公司要求,比如接下来要举的例子,我定义的scheme为wytings,然后支持的模块都集中于host字段,具体参数则全部通过query补充。比如:wytings://user?uin=10000 打开个人页面,wytings://stockDetail?marketcode=hk&stockcode=00376 打开股票详情页面等等。
要是对外部的支持,通常我们不会对每一个要支持的Activity都进行相应的intent-filter限制,而是定义一个公共的Activity进行所有外部请求的拦截形如:
<activity
android:name=".activity.SchemeFilterActivity"
android:exported="true"
android:theme="@android:style/Theme.NoDisplay"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="wytings" /> </intent-filter> <intent-filter
android:autoVerify="true"
tools:targetApi="m">
<action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <data
android:host="native.app.wytings.com"
android:scheme="http" />
<data
android:host="native.app.wytings.com"
android:scheme="https" />
</intent-filter>
</activity>
我们对这个Activity的定义进行一下说明:
a、android:exported这个属性其默认是false就是对外不开放,我们必须要设置为true,因为我们要让外部能够对其进行访问。
b、android:theme="@android:style/Theme.NoDisplay" 由于是作为拦截的Activity,所以,没必要展示,但是这个NoDisplay的theme要求必须在onResume前finish掉Activity,否则要报错。
c、第一个intent-filter自定义scheme为wytings,也就是拦截该类URL。
d、第二个scheme为http,但是加了特别的host=nativ.app.wytings.com,进一步详细拦截url为:http://nativ.app.wytings.com 的url。为什么要拦截这种url,通常情况下不用,但是特殊情况下,有时候自定义的scheme可能失效,所以而外再加层保障,当然,也要与调用方预定好url格式,比如:http://nativ.app.wytings.com/stockDetail?marketCode=hk&stockCode=00376,由于host已经被定义为别的,所以我们把具体模块定义在path里面,参数依然保留在query中。
再来看看SchemeFilterActivity的实现情况:
/**
* Created by rex on 06/10/2017.
*
* @author wytings@gmail.com
*/ public class SchemeFilterActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Uri uri = getIntent().getData();
Log.i("wytings", "uri = " + uri); String scheme = uri.getScheme();
if ("http".equals(scheme) || "https".equals(scheme)) {
String routeModule = uri.getLastPathSegment();
if (!TextUtils.isEmpty(routeModule)) {
RouteManager.getInstance().build(routeModule + "?" + uri.getQuery()).go(this);
}
} else {
RouteManager.getInstance().build(uri.toString()).go(this);
} finish();
} }
大体就是拦截,然后通过内部的RouteManager进行解析处理跳转。RouteManager怎么处理和实现就太细节了,总的来说,这个Manager的职责就是把URL翻译成具体的Intent,然后启动相应的Activity。有兴趣的同学可以自己去看看本篇文章的所有源码:
https://github.com/wytings/AndroidRoute
2、对内跳转说明
由于是应用内的实现,所以基本上,你想怎么实现就怎么实现。但是,无论多么变幻莫测,都绕不开一个核心那就是建立路由映射关系,打开相关页面,取出请求参数这三大步骤。我们逐个来分析一下。
2.1、建立路由映射关系
这个是为了能够知道特定的url到底应该展示哪个页面。通常建立一个Map,然后查找。
2.3、打开相关页面
在Android中,打开一个页面总是有自己的一套逻辑,系统那一套则是通过Intent去启动相应的组件展示。
2.4、取出参数
这个步骤,还是基于系统的Intent方式,要通过intent.getXXXExtra来取出相关参数。
这么一看好像,也没什么难度。也确实没什么难度,就单纯实现功能来说。那难点在哪呢?难点在于你决定使用注解去做这件事……为什么要用注解?因为为了哪一丁点洁癖,解藕的洁癖。结果掉进坑里了…
用注解理论上,也还好,遍历反射嘛,而且我个人测试了一下,就目前的机器真的感受不出来。当然再怎么样,也没在编译时直接生成相关代码来得快倒是真的……
于是乎,进入第三个大难题,那就是进行编译时生成代码,类似于ButterKnife一样,在编译期就生成相关代码,而不是在运行时通过反射来给变量赋值。
这里就涉及到一个东西,那就是Java 的 AbstractProcessor,这个类是在编译时生成代码最关键的类。要讲解这个得再开一篇《关于Java注解实现编译时生成代码》的文章了。同学们可以网上搜索一下基本知识,然后再看这个项目中的代码,我自己也看了很多关于注解的文章,但是很遗憾,我没看到哪篇是值得捧的,同样也没看到那篇值得喷的……我现在也没时间专门写篇关于注解的文章,但是可以给个方向,那就是先学会调试,AnnotatioProcessor的调试,跟普通java调试有点区别(自己google一下),然后就可以自己摸索了。另外,我审视了一下,我写的Annotation compiler还是蛮清晰的,你也可以试着看看。
最后,再说一遍,项目地址:AndroidRoute
有兴趣的同学,自己跑一下,胜读十年书!
关于Android路由的实现的更多相关文章
- 严选 Android 路由框架优化(下篇)
3 router 框架优化 3.1 apt 生成代码量过大问题优化 思考框架本身,其实可以发现仅有 router 映射表是需要根据注解编译生成的,其他的全部代码都是固定代码,完全可以 sdk 中直接编 ...
- 严选 Android 路由框架优化(上篇)
0 背景 早前严选 Android 工程,使用原生 Intent 方式做页面跳转,为规范参数传递,做了编码规范,使用静态方法的方式唤起 Activity public static void star ...
- Android 路由框架ARouter最佳实践
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/76165252 本文出自[赵彦军的博客] 一:什么是路由? 说简单点就是映射页面跳转 ...
- Android路由框架-ARouter详解
文章大纲 一.页面路由基本介绍1.什么是页面路由2.为什么要使用页面路由二.页面路由框架ARouter介绍1.常用功能介绍2.常见应用场景三.源码下载四.参考文章 一.页面路由基本介绍 1.什么是 ...
- WMRouter:美团外卖Android开源路由框架
WMRouter是一款Android路由框架,基于组件化的设计思路,功能灵活,使用也比较简单. WMRouter最初用于解决美团外卖C端App在业务演进过程中的实际问题,之后逐步推广到了美团其他App ...
- Android组件化、模块化、插件化
组件:指的是单一的功能组件,如地图组件(MapSDK).扫码组件(QRCode).支付组件(AnjukePay).路由组件(Router)等等: 模块:指的是独立的业务模块,如新房模块(NewHous ...
- android编码学习
虽然以下博客有点老,但很清晰,有不明白的基础知识,可以来这里找找. 2015年最新Android基础入门教程目录(完结版) 1. 环境配置 Android stodio gradle配置踩过的坑 An ...
- Android组件化方案及组件消息总线modular-event实战
背景 组件化作为Android客户端技术的一个重要分支,近年来一直是业界积极探索和实践的方向.美团内部各个Android开发团队也在尝试和实践不同的组件化方案,并且在组件化通信框架上也有很多高质量的产 ...
- 掘金 Android 文章精选合集
掘金 Android 文章精选合集 掘金官方 关注 2017.07.10 16:42* 字数 175276 阅读 50053评论 13喜欢 669 用两张图告诉你,为什么你的 App 会卡顿? - A ...
随机推荐
- java TreeSet应用
这篇是紧接着上一篇而写的,具体的实现TreeSet中有序的第二中方法 首先新建一个类,此类就是用于集合中存放的对象 然后定义一个类,实现Comparator中的CompareTo()方法 最后一个测试 ...
- Apache Camel之FTP组件学习
写在最前面 哎,最近提了离职,手头的活也基本上清理的差不多了.想着这个把月可以舒服的晃悠晃悠的离开,但是运维的小伙伴总是不架势,走之前还是提了个新需求. 先说下需求吧,我们的系统概括的讲就是一个接口系 ...
- 那些年,我们不懂的却又不得不提的 JAVA异常和异常处理!
---恢复内容开始--- 首先,我是个小小的菜鸟,最近突然突发奇想,想研究一下java的异常和异常的处理,稍有些理解,老鸟们莫要嘲笑... 既然要讲异常和异常的处理,我们就要先了解异常,那么,什么是异 ...
- NHibernte教程(10)--关联查询
本节内容 关联查询引入 一对多关联查询 1.原生SQL关联查询 2.HQL关联查询 3.Criteria API关联查询 结语 关联查询引入 在NHibernate中提供了三种查询方式给我们选择:NH ...
- JS查错小工具-三生有幸【推荐】
H5和CSS语言在开发者官网上都有在线查错工具,同样的,更加复杂的JavaScript也需要一个查错工具,(别指望DreamWeaver了,debug功能做的太垃圾,还不如Firefox自带的强..) ...
- 自制裸眼3D图【推荐】
Welcome to the World of Hidden 3D Stereograms.欢迎进入隐身3D图的世界! 网址:http://hidden-3d.com 裸眼立体图是什么? 立体图是立体 ...
- 结对编程1-四则运算(基于GUI)
林晓芳201421123092.陈惠201421123096 coding 地址:https://git.coding.net/lianlian/92.96.1.git 一.题目描述 我们在个人作业1 ...
- 团队作业8----第二次项目冲刺(Beta阶段) 第四天
BETA阶段冲刺第四天 1.小会议ing 2.每个人的工作 (1)昨天已完成的工作 1.修改了学生上传的方式: 2.完善了学生和老师修改的代码: (2) 今天计划完成的工作 (3) 工作中遇到的困难: ...
- 201521123039 《java程序设计》第八周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 总结: 1.集合可以动态修改大小,但是不可以存放基本数据类型: 2.java中任何对象都是is-a Objec ...
- 201521123067 《Java程序设计》第5周学习总结
201521123067 <Java程序设计>第5周学习总结 1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容. ●在本 ...