从0到1实现一个Android路由——初探路由

Posted xingfeng_coder

tags:

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

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

Android路由

什么是路由?最初接触路由是在大学计算机网络中,网络层IP报文传输会涉及一个路由表的概念,路由表由源IP、目的IP组成,起始就是一个映射表。Android路由也是一个映射表,映射什么呢?
这里先类比一下,如果把手机类比于浏览器,那么每个app就可以类比于一个个的网站,比如百度、头条等等,那么每个app的一个页面就可以类比于一个个网站里面的页面,浏览器的每个页面由url定义,给不同url传递不同参数,页面的表现形式还稍有不通过,这里的映射关系就是url对应页面,每个app的每个页面也可以类比于网站的页面,那是不是可以采用url的方式来定义每个页面呢?这样是不是也就有了url对应app页面的映射关系,如果有了这样的映射关系,给定一个url,那是不是就可以知道跳转到某一个具体的Activity了?Android路由其实就是解决这样的问题,那么实现一个最基础的Android路由主要有以下几步:

  1. 定义url,分配url给Activity;
  2. 建立路由表,url----->Activity
  3. 处理跳转,给定一个url,能跳转到具体的Activity。

第一个五张俱全的例子

第一个例子呢,很扯淡,但是呢,足以说明Android路由的意义。这里定义了两个Activity,其中SecondActivity用url(/secondActivity)表示,MainActivity启动SecondActivity是通过路由表来启动的,处理跳转的逻辑如下:

val routeMap = mapOf("easyrouter://demo/secondActivity" to SecondActivity::class.java)

fun goToPages(context: Context, url: String) 
    for ((key, value) in routeMap) 
        if (key == url) 
            context.startActivity(Intent(context, value))
        
    

这里就做了匹配,然后跳转,虽然很扯,但足以说明路由的精髓,后面会一步步地丰满。
这里对应最基本的路由,每一点都有:

  1. "/secondActivity"是url
  2. routeMap是路由表,这里可以理解成一个静态路由,即对应关系是硬编码的
  3. goToPages()方法处理url的跳转

下面一步步地丰满我们的EasyRouter。

外部app打开链接进入app

经常有这样的场景,在浏览器里会出现欢唤醒app的情况,唤醒后如何跳转到指定页面的呢?这里先解决这个问题,这样至少,我们的路由,外部打开内部页面是没有问题的。

清单文件注册scheme

解决这个问题,需要给我们的app里面某个页面添加scheme。这里我们用ProxyActivity进行scheme的设置,清单文件里的配置如下:

<activity android:name=".ProxyActivity">
            <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="easyrouter"
                      android:host="demo"/>
            </intent-filter>
        </activity>

这里,ProxyActivity可以被easyrouter://demo/xxxx这样的url打开。而action/category表示支持打开一些url,类似浏览器,只不过是打开easyrouter这样的scheme,而不是http或https。

Activity实现scheme跳转

再来看ProxyActivity的实现,

override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        intent.data?.apply 
            goToPages(this@ProxyActivity, path)
            finish()
        
    

intent.data可以获取从外部or其他页面传递的Uri参数,当从浏览器中打开时,链接的信息就会带过来,这里可以看到如果是easyrouter的scheme,那就交给goToPages()进行跳转。

html页面

html页面比较简单,就一个点击跳转的链接,

 <a href="easyrouter://demo/secondActivity">点击跳转到App</a>
</body>

然后用浏览器加载,第一次会提示是否用我们的demo打开,打开后就不再提示了,可以看到上面的链接也能实现从外部打开SecondActivity了。

应用内部打开外部url

所谓外部url,通常是网页,比如是应用的h5页面,Android加载网页需要用到WebView,WebView的定义如下:

override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_web_view)

        webView.apply 
            settings.apply 
                javascriptEnabled = true
                javaScriptCanOpenWindowsAutomatically = true
                setSupportMultipleWindows(true)
            
            webViewClient = WebViewClient()
            webChromeClient = WebChromeClient()
        

        webView.loadUrl(intent.getStringExtra("external_url"))
    

再回头看goToPages()对url的处理,如下:

fun goToPages(context: Context, url: String) 
    for ((key, value) in routeMap) 
        if (key == url) 
            context.startActivity(Intent(context, value))
         else if (url.startsWith("http")) 
            context.startActivity(Intent(context, WebViewActivity::class.java).apply 
                putExtra("external_url", url)
            )
        
    

可以看到,针对http开头的url,交由WebViewActivity进行加载。

总结

至此,第一个足以说明路由概念的例子就结束了,主要有静态路由表,控制路由跳转的逻辑,支持了外部应用跳转到应用,也支持应用内跳转原生页面和网页页面。那么一个优秀的路由应该是怎样的呢?或者说这个例子有哪些不足呢?

  1. 静态路由表,如果应用有很多应用,一个个的添加是不是很难维护?
  2. 跳转还不支持传参、不支持拦截
  3. 没有降级策略,比如有人恶意输入一个不存在页面的scheme,那app就显示不正常了。

后面会根据上面的几个不足一步步地完善路由。

关于代码,可以参考first_demo分支的代码。

参考阅读

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

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

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

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

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

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

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

Android 9 Audio系统笔记:音频路由实现——从AudioTrack到audiohal