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

Posted xingfeng_coder

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从0到1实现一个Android路由——URL解析器相关的知识,希望对你有一定的参考价值。

从0到1实现一个android路由系列文章

从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拦截、传参、降级的功能。关于代码,可以参考url_processor分支

参考阅读

关注我的技术公众号,不定期会有技术文章推送,不敢说优质,但至少是我自己的学习心得。微信扫一扫下方二维码即可关注:

以上是关于从0到1实现一个Android路由——URL解析器的主要内容,如果未能解决你的问题,请参考以下文章

从0到1实现一个Android路由——拦截请求再跳转

从0到1实现一个Android路由——拦截请求再跳转

从0到1实现一个Android路由——对Kotlin模块的支持

从0到1实现一个Android路由——APT收集路由

从0到1实现一个Android路由——多模块的APT收集路由

Flask之Request请求