美文网首页
Rexxar Android 系列学习(5) 过滤拦截

Rexxar Android 系列学习(5) 过滤拦截

作者: 無名小子的杂货铺 | 来源:发表于2017-07-19 17:16 被阅读206次

    Rexxar 有很多拦截资源请求操作,刚看的时候乱的很,这里是结合缓存来实现的,下一节会介绍缓存机制,这里我们就需要知道返回给 WebView 的 WebResourceResponse 数据都是从缓存中读取即可。

    所有的代码都在 RexxarWebViewClient 类当中,只需要看 handleResourceRequest(WebView webView, String requestUrl) 这一个方法。

    具体过程

    Rexxar 拦截 html,js 资源直接渲染进程返回,图片等其他资源先返回空的数据流再异步向流中写数据,因为渲染线程做太多工作会耗时并且 block 页面渲染,造成不好的显示效果。

    我这里只介绍关于Html部分,js 同理。

    首先需要判断当前url是否需要拦截处理,不需要则走系统方法,让webview自行处理,满足条件才拦截处理,这里 url 需要满足 非null 非本地 host 是豆瓣相关域名,详细就不多说了, 可以看代码:

      /**
       * @param requestUrl
       * @return
       */
      private boolean shouldIntercept(String requestUrl) {
          if (TextUtils.isEmpty(requestUrl)) {
              return false;
          }
          // file协议需要替换,用于html
          if (requestUrl.startsWith(Constants.FILE_AUTHORITY)) {
              return true;
          }
    
          // rexxar container api,需要拦截
          if (requestUrl.startsWith(Constants.CONTAINER_API_BASE)) {
              return true;
          }
    
          // 非合法uri,不拦截
          Uri uri = null;
          try {
              uri = Uri.parse(requestUrl);
          } catch (Exception e) {
              e.printStackTrace();
          }
          if (null == uri) {
              return false;
          }
    
          // 非合法host,不拦截
          String host = uri.getHost();
          if (TextUtils.isEmpty(host)) {
              return false;
          }
    
          // 不能拦截的uri,不拦截
          Pattern pattern;
          Matcher matcher;
          for (String interceptHostItem : ResourceProxy.getInstance().getProxyHosts()) {
              pattern = Pattern.compile(interceptHostItem);
              matcher = pattern.matcher(host);
              if (matcher.find()) {
                  return true;
              }
          }
          return false;
      }
    

    WebResourceResponse

    WebResourceResponse 是关键的返回对象,会构造一个正确类型的输入流返回给 WebView ,不为 null WebView 就不会自己去下载了,也就节省了 WebView 访问网络资源。

    图片异步返回

    这部分是过滤拦截中比较重要的部分,代码较为复杂凌乱,主要是有很多错误情况处理,应为并不是每次数据都是合理和正确的。

    这里采用的方案是:先返回一个空的 InputStream,然后再通过异步的方式向里面写数据。

        String fileExtension = MimeTypeMap.getFileExtensionFromUrl(requestUrl);
        String mimeType = MimeUtils.guessMimeTypeFromExtension(fileExtension);
    

    首先要获取 url 的扩展名,也就是是什么类型的文件,然后根据类型获取 MimeType,在创建 WebResourceResponse 的时候传入,才是合理的类型。

    WebResourceResponse xResponse = new WebResourceResponse(mimeType, "UTF-8", in);
    

    然后在渲染线程中 post 一个 Runnable 异步的返回数据,当然这里做了 try catch 处理,如果期间出现异常,直接调用 super.shouldInterceptRequest(webView, requestUrl) 方法,让系统处理,从而不影响原生功能使用。

    因为在返回空的 InputStream 时,我们已经创建了 mOut 对象,所以在 ResourceRequest 线程中,需要在获取到数据时通过 mOut 写如数据。

    例如:

        byte[] bytes = IOUtils.toByteArray(cacheEntry.inputStream);
                    LogUtils.i(TAG, "load async cache hit :" + mUrl);
                    mOut.write(bytes);
    

    这是一次正常的读取缓存成功操作并返回。

    还有使用 native 访问网络处理的情况,相对缓存就是多了一步下载图片或者文件的操作,并且成功也要缓存到本地。同样需要对数据进行严格校验,出现任何失败都要分会相应的错误状态。

    具体错误类型就不介绍了,这个可能和业务有关。

    RexxarContainerAPI

    这里简单介绍下 RexxarContainerAPI,和 RexxarWidget 类似,可以给 Web 一个 Native 的计算结果。RexxarContainerAPI 可以有很多的实现类,每一种都代表一种 Api 请求类型,用来处理不同的业务,只需要在不用业务页面添加所需要的 Api 功能即可,提供了一种通用的处理机制。

    例如:

        / / 设置local api
        mRexxarWebView.addContainerApi(new FrodoContainerAPIs.LocationAPI());
        mRexxarWebView.addContainerApi(new FrodoContainerAPIs.LogAPI());
    

    这里引用下官方介绍:

    我们为 iOS 和 Android 各开发了一个 Rexxar Container。iOS 和 Android 平台截获请求的方式由于平台差异,并不完全相同。但本质上都是在 Web 和 Native 之间实现了一个 Proxy。Web 发出的请求会被 Proxy 预先处理。要么是修改后再发出去,要么是由 Rexxar Container 自己处理。

    Rexxar Android 系列学习其他文章

    Rexxar Android 系列学习(1) 项目结构
    Rexxar Android 系列学习(2) 路由协议
    Rexxar Android 系列学习(3) Native 和 web 交互
    Rexxar Android 系列学习(4) 错误处理
    Rexxar Android 系列学习(5) 过滤拦截
    Rexxar Android 系列学习(6) 缓存机制

    相关文章

      网友评论

          本文标题:Rexxar Android 系列学习(5) 过滤拦截

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