欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

VasSonic之流式拦截

程序员文章站 2022-04-21 12:04:53
...

VasSonic之流式拦截

VasSonic框架用到了流式拦截和增量更新技术,下面只简单介绍流式拦截,详细参考:https://github.com/Tencent/VasSonic/wiki
VasSonic之流式拦截

一)传统H5页面打开缓慢的原因?

1.打开一个H5页面首先需要初始化WebView内核和渲染组件(冷启动耗时200~500ms,冷启动过程中网络处于空等状态)
2.完成初始化后,WebView在CDN上请求Html页面,数据回来后再对DOM进行操作更新

二)Sonic框架如何优化Webview初始化过程中网络空等问题?

针对网络空闲问题,Sonic做了并行请求,通过Native建立http链接获取html数据,充分利用这段空闲时间。最理想的情况是html数据下载完成,Webview还没初始化好,等Webview初始化完成直接加载本地html;当Webview初始化完成,html还没下载完,这时就要提到流式拦截技术了
VasSonic之流式拦截

三)流式拦截如何实现?

将Html已读流(memStream)和未读流(netStream)桥接成SonicSessionStream,SonicSessionStream继承InputStream并重写read方法,SonicSessionStream包装成WebResourceResponse对象,通过webview拦截接口shouldInterceptRequest将WebResourceResponse回传给webview,SonicSessionStream代码如下:

public class SonicSessionStream extends InputStream{
  // 未加载HTML流
  private BufferedInputStream netStream;
  // 已加载HTML流
  private BufferedInputStream memStream;

  // 省略非关键代码
  @Override
  public synchronized int read() throws IOException {

    int c = -1;

    try {
      if (null != memStream && !memStreamReadComplete) {
        c = memStream.read();
      }

      if (-1 == c) {
        memStreamReadComplete = true;
        if (null != netStream && !netStreamReadComplete) {
          c = netStream.read();
          if (-1 != c) {
            outputStream.write(c);
          } else {
            netStreamReadComplete = true;
          }
        }
      }
    } catch (Throwable e) {
      Log.e(TAG, "read error:" + e.getMessage());
      if (e instanceof IOException) {
        throw e;
      } else {//Turn all exceptions to IO exceptions to prevent scenes that the kernel can not capture
        throw new IOException(e);
      }
    }

    return c;
  }
  // 省略非关键代码
}

在webview拦截接口shouldInterceptRequest中处理mSonicSessionStream,代码如下:

mWebView.setWebViewClient(new WebViewClient() {

      @Override
      public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        if (mMallHtmlStream != null && isInterceptByWebView.get() && isMatchCurrentUrl(url)) {
          String mime = MallHtmlUtils.getMime(url);
          return new WebResourceResponse(mime, "utf-8", mSonicSessionStream);
        }
        return super.shouldInterceptRequest(view, url);
      }
    });

核心思想是充分利用webview初始化的时间,由native建立http链接请求HTML资源,在webview初始化完成前,尽可能的多请求HTML数据,等webview完成初始化立即将HTML提供给Webview渲染。