前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从0到1实现一个Android路由(2)——URL解析器

从0到1实现一个Android路由(2)——URL解析器

作者头像
用户1108631
发布2019-08-17 12:40:16
5390
发布2019-08-17 12:40:16
举报

在从0到1实现一个路由(1)——初探路由中,介绍了一个五脏俱全的路由例子,路由是通过URL到达页面,那么URL解析器是个很重要的步骤,负责解析、跳转、拦截、传参等等。

所谓URL解析器,可以看成是URL和Intent的映射,因为Android启动页面只能通过Intent来跳转,不论是显试调用还是隐式调用,归根结底是一个Intent。

URL解析器改造

在上个例子的基础上,进行改造,将URL解析器作为单独模块抽出。

结构如下:

fun urlProcess(context: Context, url: String): Intent? {    return null}

URL传参

通过URL到达页面,URL是可以携带参数的,比如GET请求中的url就是含有参数的,我们可以利用该特性对第一篇中的例子加以改造。

URL格式定义

URL形式为scheme://host:port/path?query

query的形式为key1=value1&key2=value2。

携带参数的路由跳转

定义好格式后,新的路由跳转修改为:

//本app支持的scheme    else if (url.startsWith("easyrouter")) {        with(URI(url)) {            for ((key, value) in routeMap) {                if (key.equals(path)) {                    return Intent(context, value).apply {                        if (!TextUtils.isEmpty(query)) {                            query.split("&").forEach {                                it.split("=").apply {                                    putExtra(get(0), get(1))                                }                            }                        }                    }                }            }        }    }

主要改变是url只要以路由表中的key开头,就能跳转到该Activity,同时也允许不传参的跳转,带有参数的则解析然后放到Intent中进行跳转。 这样的方式需要注意页面对默认值的一些处理,因为有时有些key可能是不提供的。

调用方

    val paramsActivityUrl = "/paramsActivity"    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)        btnWithParams.setOnClickListener {            goToPages(this, paramsActivityUrl + "?firstname=hello&secondname="world")        }        btnWithoutParams.setOnClickListener {            goToPages(this, paramsActivityUrl)        }    }}

定义好了key之后,再从ParamsActivity中取出就可以了。

URL拦截

经常会遇到跳转到一个页面之前需要首先进行登录操作,那么如果在没有登录的状态下,需要先跳转到登录页面。这里就可以通过URL拦截来实现登录拦截。

拦截需要考虑的点是:如何在拦截后继续跳转到目的页面。比如登录拦截,登录页面好启动,登录成功后,通常逻辑是进入首页,这时如何跳转到目的页面呢?关于这一点,因为原有的页面跳转逻辑都是有的,比如登录成功后就跳转到首页,而现在需要改变跳转逻辑,实现的话侵入会比较严重,需要用到Hook。在寻求解决方案中,先看个简单点的拦截。

举个例子:在跳转SecondActivity之前弹出一个对话框来决定是否继续跳转,新的处理逻辑如下:

un goToPages(context: Context, url: String) {    if (url.contains("/secondActivity")) {        AlertInterceptor().interceptor(context, URI(url),            object : OnSuccessListener {                override fun onSuccess(context: Context, uri: URI) {                    urlProcess(context, url)?.apply {                        context.startActivity(this)                    }                }            },            object : OnErrorListener {                override fun onError() {                    Toast.makeText(context, "用户取消了跳转", Toast.LENGTH_SHORT).show()                }            }        )    } else {        urlProcess(context, url)?.apply {            context.startActivity(this)        }    }}

在处理url之前,首先交给AlerInterceptor处理一把,通过两个接口将是否继续跳转通知出来。Interceptor的结构如下:

nterface OnErrorListener {    fun onError()}interface OnSuccessListener {    fun onSuccess(context: Context, uri: URI)}interface Interceptor {    fun interceptor(        context: Context,        uri: URI,        onSuccessListener: OnSuccessListener? = null,        onErrorListener: OnErrorListener? = null    )}class AlertInterceptor : Interceptor {    override fun interceptor(        context: Context,        uri: URI,        onSuccessListener: OnSuccessListener?,        onErrorListener: OnErrorListener?    ) {        AlertDialog.Builder(context).apply {            setTitle("拦截提示")            setMessage("是否跳转SecondActivity")            setPositiveButton(                "确定"            ) { dialog, _ ->                onSuccessListener?.onSuccess(context, uri)                dialog.dismiss()            }            setNegativeButton(                "取消"            ) { dialog, _ ->                onErrorListener?.onError()                dialog.dismiss()            }        }.create().show()    }}

降级策略

url匹配,如果匹配不到Activity那应该怎么办?是否可以跳转到一个默认页面,比如说首页?

这里可以通过降级策略来实现。 可以通过接口暴露给上层,交由开发者自己实现,这里就先简单写死,概念最重要。

在urlProcess()方法最后加上一个默认的Intent,如下:

fun urlProcess(context: Context, url: String): Intent? {    ...    return Intent(context, DegradeActivity::class.java).apply {        putExtra("error_msg", "没有找到目标页面")    }}

总结

本文主要在第一个的例子上增加了URL解析器,增加了URL拦截、传参、降级的功能。关于代码,可以参考https://github.com/wangli135/EasyRouter/tree/url_processor。

参考阅读

  • https://juejin.im/entry/5897a1c8128fe10058e76368
  • https://juejin.im/post/5bfb5dbe5188254e2a043489
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 每天学点Android知识 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • URL解析器改造
    • URL传参
      • URL格式定义
      • 携带参数的路由跳转
      • 调用方
    • URL拦截
      • 降级策略
      • 总结
      • 参考阅读
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档