先说一下背景,目前有需求从外部包括其他应用和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路由的实现的更多相关文章

  1. 严选 Android 路由框架优化(下篇)

    3 router 框架优化 3.1 apt 生成代码量过大问题优化 思考框架本身,其实可以发现仅有 router 映射表是需要根据注解编译生成的,其他的全部代码都是固定代码,完全可以 sdk 中直接编 ...

  2. 严选 Android 路由框架优化(上篇)

    0 背景 早前严选 Android 工程,使用原生 Intent 方式做页面跳转,为规范参数传递,做了编码规范,使用静态方法的方式唤起 Activity public static void star ...

  3. Android 路由框架ARouter最佳实践

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/76165252 本文出自[赵彦军的博客] 一:什么是路由? 说简单点就是映射页面跳转 ...

  4. Android路由框架-ARouter详解

    文章大纲 一.页面路由基本介绍1.什么是页面路由2.为什么要使用页面路由二.页面路由框架ARouter介绍1.常用功能介绍2.常见应用场景三.源码下载四.参考文章   一.页面路由基本介绍 1.什么是 ...

  5. WMRouter:美团外卖Android开源路由框架

    WMRouter是一款Android路由框架,基于组件化的设计思路,功能灵活,使用也比较简单. WMRouter最初用于解决美团外卖C端App在业务演进过程中的实际问题,之后逐步推广到了美团其他App ...

  6. Android组件化、模块化、插件化

    组件:指的是单一的功能组件,如地图组件(MapSDK).扫码组件(QRCode).支付组件(AnjukePay).路由组件(Router)等等: 模块:指的是独立的业务模块,如新房模块(NewHous ...

  7. android编码学习

    虽然以下博客有点老,但很清晰,有不明白的基础知识,可以来这里找找. 2015年最新Android基础入门教程目录(完结版) 1. 环境配置 Android stodio gradle配置踩过的坑 An ...

  8. Android组件化方案及组件消息总线modular-event实战

    背景 组件化作为Android客户端技术的一个重要分支,近年来一直是业界积极探索和实践的方向.美团内部各个Android开发团队也在尝试和实践不同的组件化方案,并且在组件化通信框架上也有很多高质量的产 ...

  9. 掘金 Android 文章精选合集

    掘金 Android 文章精选合集 掘金官方 关注 2017.07.10 16:42* 字数 175276 阅读 50053评论 13喜欢 669 用两张图告诉你,为什么你的 App 会卡顿? - A ...

随机推荐

  1. mysql存储过程 基本语法

    话不多说 一.MySQL 创建存储过程 "pr_add" 是个简单的 MySQL 存储过程,这个存储过程有两个 int 类型的输入参数 "a"."b& ...

  2. MongoDB-python的API手记

    -------------------python调用MongoDB------------------- 1.官方文档:http://api.mongodb.org/python/current/t ...

  3. python爬虫scrapy框架——人工识别知乎登录知乎倒立文字验证码和数字英文验证码

    目前知乎使用了点击图中倒立文字的验证码: 用户需要点击图中倒立的文字才能登录. 这个给爬虫带来了一定难度,但并非无法解决,经过一天的耐心查询,终于可以人工识别验证码并达到登录成功状态,下文将和大家一一 ...

  4. 分享45个android实例源码,很好很强大.收藏吧!!!

    andriod闹钟源代码 http://www.apkbus.com/android-20974-1-1.html android源码分享之指南针程序 http://www.apkbus.com/an ...

  5. group by 多字段分组

    在平时的开发任务中我们经常会用到MYSQL的GROUP BY分组, 用来获取数据表中以分组字段为依据的统计数据.比如有一个学生选课表,表结构如下: Table: Subject_Selection S ...

  6. 201521123083 《Java程序设计》第6周学习总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 1.2 可选:使用常规方法总结其他上课内容. protec ...

  7. 团队作业4——第一次项目冲刺(Alpha版本)第六天and第七天

    团队作业4--第一次项目冲刺(Alpha版本)第六天and第七天 第一次项目冲刺(Alpha版本)第六天 一.Daily Scrum Meeting照片   二.燃尽图 1.解释说明横纵坐标代表的含义 ...

  8. Android四大组件(详细总结)

    android四大组件分别为activity.service.content provider.broadcast receiver. 一.android四大组件详解 1.activity (1)一个 ...

  9. java第十四次作业

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自 ...

  10. 201521123050 《Java程序设计》第14周学习总结

    1. 本周学习总结 2. 书面作业 1. MySQL数据库基本操作 1.1立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自己的学号.姓名) 在自己建立的数据库上执行常见SQL语句(截图) ...