Android 离线加载落地

Android 离线加载落地

作者简介:Serpit,Android开发工程师,2023年加入37手游技术部,目前负责国内游戏发行 Android SDK 开发。

前言

在使用WebView时,会有一个老生常谈的话题------"WebView加载优化"。那WebView加载优化,一般有几个方向:

  • WebView的预创建和复用
  • WebView代理请求
  • WebView的离线加载

这里简单科普一下这几个优化方向(大佬可以直接忽略~~)

预创建和复用

预创建和复用,见名知意,就是可以提前缓存一些WebView。这是因为,在WebView创建的时候,会需要一点时间,所以,为了节省这部分的时间,可以提前实例化WebView。这里可以使用缓存池来实现~

代理请求

代理请求,该方案是接管WebView的一些请求,帮助前端页面做请求,然后通过与前端的交互,将数据带回给前端页面。那,为什么要这么做呢?那也是"抢跑",提前在跳转/其他时机的时候,同时做一些网络请求,将业务数据处理好,等到前端页面加载好的时候,来客户端取即可。这样就节省了前端做请求的耗时了~

简单介绍完预创建和复用、WebView代理请求,接下来就介绍本文的离线加载了。

离线加载

离线加载是节省的哪一部分耗时呢?回答这个问题前,先了解下离线加载是个什么方案。

离线加载的原理是,拦截WebView的请求,转而在端内构造对应的响应来进行返回。所以,离线加载节省的是请求资源的耗时,快速页面的渲染。

如何落地?

落地这个离线加载,是离不开WebViewClient中一个关键的API

java 复制代码
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)

这个API是我们完成资源拦截的关键,它的Request参数,带有当前WebView正要加载资源的URL,而返回值WebResourceResponse则是返回给WebView,当前资源的响应。

下面就是伪代码

java 复制代码
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        WebResourceResponse webResourceResponse = fetchResource(request); //根据请求匹配资源
    if (webResourceResponse != null) {
        return webResourceResponse;
    }
    return super.shouldInterceptRequest(view, request);
}


private WebResourceResponse fetchResource(WebResourceRequest webResourceRequest) {
        String url = webResourceRequest.getUrl().toString();
        Uri uri = Uri.parse(url);
        File file = findFileLocal(uri); //省略匹配的逻辑...
        return new WebResourceResponse(mime, "UTF-8", new FileInputStream(file));
    }

有了这个强有力的API的,我们就可以轻松实现离线加载了。是不是很简单~

资源

因为离线加载除了加载逻辑以外,还有一个核心的点------资源!那资源管理这部分也是十分重要,下面将介绍资源管理部分需要注意的点和方案。由于我们的资源是前端资源,所以会有版本管理的需求,毕竟前端更新的时候本地的资源也需要更新,否则,加载出来的页面就会有问题。下面就介绍一下如何可以做到更新同步的。

更新注意的点有以下几个:

  • 更新时机
  • 更新策略

更新时机

更新时机,一般来说,在APP启动的时候会需要有一个检查的机制,检查当前的资源是否最新。然后防止用户在使用的过程中,前端有更新,也会在打开页面前做一次更新,确保用户的页面不受旧缓存影响。因此,更新的时机有两个,应用启动和打开页面。

更新策略

更新策略,也按应用启动和打开页面,有两个流程,下面用流程图的方式给大家介绍一下。

打开APP流程

在打开APP时,需要异步检查本地的离线包hash值是否与线上最新的版本一致,不一致则更新本地离线包,然后在更新成功后,则保存最新的离线包。当然,资源包目前只是做的整包更新,还可以在这个基础上优化做资源包的差分处理,做到增量资源包更新。这里先不展开,有兴趣的同学可以留言讨论~

打开页面更新流程

在打开页面前,也需要做一次检查,检查离线包是否最新,但这里有一个注意点和APP启动流程不太一样,因为更新离线资源是一个耗时的操作,所以当检查到本地不是最新时,需要把拦截WebView请求的逻辑给去除,让本次加载走线上的资源,同时等待下次资源最新可用的时候,才开启离线加载。

资源怎么来?

资源怎么来?很多同学会说,这不是废话吗?那当然从前端和后端资源服务接口来呀。这是肯定,没错的。但是,在调研初期,没有前端和后端同学的帮助时,又该如何验证可行性呢?这里安利一个Chrome的小插件Save All Resources。这个插件可以把浏览器的请求资源拦截到本地文件夹中,是不是一个妥妥的调研神器~

万事具备,落地!

不知大家是否还记得,在上一篇WebView文章中提到的"WebHook"概念呢?没有看过的同学可以回头看下这个这是你们项目中WebView的样子吗?。在这里我们可以实现一个LocalH5WebHook,然后针对一些开关和更新策略,对这个WebHook进行插拔,就可以灵活实现对离线加载功能的控制了。

java 复制代码
public class LocalH5WebHook extends SimpleWebHook {
     //... 省略其他代码
     public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        WebResourceResponse webResourceResponse = fetchResource(request);
        if (webResourceResponse != null) {
            return webResourceResponse;
        }
        return super.shouldInterceptRequest(view, request);
    }
}

总结

上述介绍了一些的WebView优化思路还有落地离线加载的过程,希望可以对一些小伙伴有作用,也欢迎小伙伴们讨论和给些建议~

相关推荐
阿巴斯甜18 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker19 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq952720 小时前
Andorid Google 登录接入文档
android
Wect20 小时前
浏览器缓存机制
前端·面试·浏览器
黄林晴21 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿2 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇2 天前
AOSP15 Input专题InputReader源码分析
android