美文网首页WebViewAndroid知识Android开发
ARouter解析三:URL跳转本地页面源码分析

ARouter解析三:URL跳转本地页面源码分析

作者: juexingzhe | 来源:发表于2017-07-06 00:27 被阅读1344次

    在前面文章中对ARouter中页面跳转和源码进行了分析,今天我们来学习下通过URL跳转本地页面的使用和跳转源码分析。在看这篇文章之前建议小伙伴们先看下ARouter解析一:基本使用及页面注册源码解析,先对ARouter有个整体的了解。

    通过URL跳转也免不了前面的准备工作,比如ARouter实例的获取,初始化,构造路由信息的PostCard,PostCard的完善等都是一样的,我们这里就不再重复炒饭了,有需要的同学自行参考ARouter解析二:页面跳转源码分析.

    栗子还是用的官方Demo,看下跳转效果。

    主界面.png

    点击“通过URL跳转”,会通过WebView加载html文件:

    链接H5.png

    点击第一个链接会跳转到Test1Activity界面:

    Test1Activity.png

    接下来我们先来看下URL跳转到本地页面怎么使用。

    1.URL跳转简单使用

    首先需要加载一个H5页面,使用方式还是一致的,通过单例模式获取ARouter实例,传入path“/test/webview”构建PostCard,用来存储跳转的所有信息。传入一个H5页面地址的参数,调用navigation就可以跳转到path路径对应的界面。

    ARouter.getInstance().build("/test/webview")
                         .withString("url", "file:///android_asset/schame-test.html")
                         .navigation();
    

    我们看下这个界面的代码,逻辑很简单。通过WebView加载url对应的H5页面,也就是前面传入的htmlfile:///android_asset/schame-test.html

    @Route(path = "/test/webview")
    public class TestWebview extends Activity {
    
        WebView webview;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_test_webview);
    
    
            webview = (WebView) findViewById(R.id.webview);
            webview.loadUrl(getIntent().getStringExtra("url"));
        }
    }
    

    简单看下html界面的代码,简单我们就看下第一个跳转链接的效果。点击会会触发href属性的链接arouter://m.aliyun.com/test/activity1.

    <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title></title>
    </head>
    
    <body>
    
    <h2>跳转测试</h2>
    
    <h2>自定义Scheme[通常来说都是这样的]</h2>
    <p><a href="arouter://m.aliyun.com/test/activity1">arouter://m.aliyun.com/test/activity1</a></p>
    <p><a href="arouter://m.aliyun.com/test/activity1?url=https%3a%2f%2fm.abc.com%3fa%3db%26c%3dd">测试URL Encode情况</a></p>
    <p><a href="arouter://m.aliyun.com/test/activity1?name=alex&age=18&boy=true&high=180&obj=%7b%22name%22%3a%22jack%22%2c%22id%22%3a666%7d">arouter://m.aliyun.com/test/activity1?name=alex&age=18&boy=true&high=180&obj={"name":"jack","id":"666"}</a></p>
    <p><a href="arouter://m.aliyun.com/test/activity2">arouter://m.aliyun.com/test/activity2</a></p>
    <p><a href="arouter://m.aliyun.com/test/activity2?key1=value1">arouter://m.aliyun.com/test/activity2?key1=value1</a></p>
    <p><a href="arouter://m.aliyun.com/test/activity3?name=alex&age=18&boy=true&high=180">arouter://m.aliyun.com/test/activity3?name=alex&age=18&boy=true&high=180</a></p>
    
    <h2>App Links[防止被App屏蔽]</h2>
    <p><a href="http://m.aliyun.com/test/activity1">http://m.aliyun.com/test/activity1</a></p>
    <p><a href="http://m.aliyun.com/test/activity2">http://m.aliyun.com/test/activity2</a></p>
    
    </body>
    </html>
    

    有没有感觉很神奇?为什么点击一个链接会跳转到我们 本地的页面?继续往后看就有分晓了。

    URL的跳转很简单就是一句话,和页面跳转的逻辑是一样的,这里多了一个加载H5页面的步骤,只不过是为了模拟URL跳转本地界面的功能。

    2.URL跳转源码分析

    在上面我们留了个疑问,为什么在WebView中点击一个链接能跳转到我们APP本地的页面?一般会有个常用的做法,就是给WebView添加一个WebViewClient,然后实现shouldOverrideUrlLoading方法,在方法中构造intent进行跳转。逻辑示意代码就是这样:

    webview.setWebViewClient(new WebViewClient(){
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    if (url != null && url.contains("arouter")){
                        Intent intent = new Intent(TestWebview.this, Test1Activity.class);
                        startActivity(intent);
                        return true;
                    }
                    return super.shouldOverrideUrlLoading(view, url);
                }
    });
    

    通过* shouldOverrideUrlLoading*拦截url跳转,然后根据自己的需要进行跳转。那么ARouter是这样的吗?淡然不是了,要不就没有这篇分享的必要了,逃:)

    首先我们先来分析下,上面这种写法的缺点。

    1.在webView中直接写跳转逻辑,有点硬编码的味道,另外如果一个APP中有很多页面需要这种跳转逻辑,不可能每个界面添加一个WebView控件,只能在父类界面中添加共同添加一个WebView控件,然后统一进行拦截,那么这时候逻辑就会显得有点臃肿了。

    2.另外一个缺点就是,比如另外一个应用需要跳转到我们APP的Test1Activity怎么做?这时候就不是在自己APP的WebView环境中了,这种方法就起不了作用了。所以在大型APP中不是一种很好的设计。

    那么ARouter怎么做的呢?小伙伴们还记得隐式跳转吗?ARouter就是通过注册一个没有UI的界面来统一处理scheme是arouter的跳转请求。我们看下代码:

    <activity android:name=".SchemeFilterActivity">
    
                <!-- Schame -->
                <intent-filter>
                    <data
                        android:host="m.aliyun.com"
                        android:scheme="arouter"/>
    
                    <action android:name="android.intent.action.VIEW"/>
    
                    <category android:name="android.intent.category.DEFAULT"/>
                    <category android:name="android.intent.category.BROWSABLE"/>
                </intent-filter>
            </activity>
    

    在清单文件中注册了SchemeFilterActivity这个activity,scheme就是arouter, host就是m.aliyun.com,其中有个categoryandroid.intent.category.BROWSABLE,这样就可以在WebView中跳转SchemeFilterActivity这个界面了。有个注意点,能跳转SchemeFilterActivity的必要条件就是需要匹配intent-filter中的data, action, category的标签,其中category匹配任意一个即可。接着看下SchemeFilterActivity这个界面:

    public class SchemeFilterActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
    //        直接通过ARouter处理外部Uri
            Uri uri = getIntent().getData();
            ARouter.getInstance().build(uri).navigation(this, new NavCallback() {
                @Override
                public void onArrival(Postcard postcard) {
                    finish();
                }
            });
        }
    }
    

    会不会有的小伙伴不相信会跳到这?还不信我的人品吗?好吧,我在这里面打了个断点,我没骗人吧。同时可以看到拿到了H5界面点击的链接arouter://m.aliyun.com/test/activity1.

    SchemeFilterActivity.png

    有了这个链接,后面其实就是页面跳转的逻辑了,同ARouter解析二:页面跳转源码分析源码跳转是一致的,这里就不再粘贴一次了。

    那么这样使用有什么好处呢?

    1.首先就是页面跳转的灵活性,比如需要和H5中进行通信,H5需要跳转到APP本地的页面,Native和H5只需要统一一个path文档即可,H5通过path构造一个url就可以实现跳转到对应页面的功能,很类似浏览器,实现很好的解耦。

    2.相比较于隐式的intent,每一个从外面跳转进来的页面都需要注册上intent-filter,每个页面都需要设置export=true,也就是需要让每一个页面都可以导出,在外部可以访问到。这样做会带来非常严重的安全风险,就像是一个房子有十个门还是只有一个门,看门的成本是不同的。而现在使用的这种场景只需要对外暴露出一个activity,然后在这个activity中注册一个intent-filter,这样之后所有的外部路由请求都会经过这唯一的门,然后在这个activity中获取到URL并将其交给ARouter,剩下的就由路由框架做分发了。

    3.另外一个好处就是隐式intent跳转无法将参数自动注入,ARouter可以在url中携带参数然后自动注入,这个我们这次分享没有涉及到,下一个分享会涉及。

    3.总结

    今天URL跳转本地页面源码的内容就是这些,有了前面两篇分享的基础到这里就比较轻松愉快了。使用方式都是都是一行代码搞定,和Activity跳转不同的就是需要考虑外部导航到本地页面的需求,因此需要在清单文件中声明一个activity,这个activity不需要页面,用来统一获取url请求,然后再交给路由框架进行跳转。

    今天的URL跳转本地页面源码分析的车就开到这了,大家可以下车喽。有些跳转细节不清楚的可以参考前面的分享:
    ARouter解析一:基本使用及页面注册源码解析
    ARouter解析二:页面跳转源码分析

    你们的赞是我坚持下去最大的动力,谢谢!

    欢迎关注公众号:JueCode

    相关文章

      网友评论

      • Bugme:请问下,a标签下href写了arouter的格式的地址,如果要在浏览器上访问的话要在吗解决?
        HopeMan:先说下arouter协议是怎么跳转到具体app的:系统浏览器发现要加载一个连接,是以arouter开头的协议,但是其自身无法处理该协议,此时就会把此协议往系统层抛,系统会根据所有安装的app的清单文件决定要将此协议交给哪个app来处理,就是文中的书写方式。所以如果要在浏览器上访问,那么浏览器就要自己处理此协议,否在就会交给某个具体app处理
      • 凸图土吐:你好 关注你的这个路由框架原理解析 非常棒
        但是能否进行拦截Fragment 我发现好像纯粹就是获取Fragment的实例 是否可以动动源码 可以实现拦截Fragment呢 :smile:

      本文标题:ARouter解析三:URL跳转本地页面源码分析

      本文链接:https://www.haomeiwen.com/subject/vgdchxtx.html