Glide 玩转 WebView缓存

2023-02-23  本文已影响0人  米奇小林

最近接到个奇葩需求,缓存webview,我想着webview不是自带缓存么,奈何手上这个设备由于网络等各种限制问题,导致webview不能直接加载H5中的资源。也就是说原生缓存机制啥的用不了。

思路:

1.H5本身是html文件,可以想办法保存在本地。

2.H5内的图片可以通过Glide来处理。设置WebViewClient,通过shouldInterceptRequest 拦截所有的资源请求,将图片交给Glide。

开搞: 这里有个问题H5本身怎么保存,估计要写很多代码吧,对于我这个懒人来说太麻烦,html本身就是文件,能不能用glide来处理尼。

查资料发现Glide Decode:

142245.png

里面有File,那么是不是完全可以把h5一个链接当作file使用glide加载了。上代码

1.先处理Glide加载图片部分,新建一个专门处理各种资源的工具类

public class GlideUtil {

    public static byte[] syncLoad(String url, String type) {
        GlideUrl glideUrl = buildUrl(url);
        byte[] bt = null;
        switch (type) {
            case "gif":
                FutureTarget<byte[]> targetGif = Glide.with(App.instance)
                        .as(byte[].class)
                        .load(glideUrl)
                        .decode(GifDrawable.class).submit();
                try {
                    bt = targetGif.get();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                break;
            case "img":
                FutureTarget<Bitmap> targetImg = Glide.with(App.instance)
                        .asBitmap().load(glideUrl).submit();
                try {
                    Bitmap bitmap = targetImg.get();
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
                    bt = baos.toByteArray();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
            case "html":
                FutureTarget<File> targetHtml = Glide.with(App.instance)
                        .asFile()
                        .load(glideUrl)
                        .submit();
                try {
                    File file = targetHtml.get();
                    FileInputStream fis = new FileInputStream(file);
                    //新的 byte 数组输出流,缓冲区容量1024byte
                    ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
                    //缓存
                    byte[] b = new byte[1024];
                    int n;
                    while ((n = fis.read(b)) != -1) {
                        bos.write(b, 0, n);
                    }
                    fis.close();
                    //改变为byte[]
                    bt = bos.toByteArray();
                    //
                    bos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
        }
        return bt;
    }

    public static GlideUrl buildUrl(String url){
        GlideUrl cookie = new GlideUrl(url, new LazyHeaders.Builder()
                .addHeader("Cookie", "2")
                .build());
        return cookie;
    }
}

这里为什么要返回byte[],往下看

2.webview 设置 WebViewClient,重写 shouldInterceptRequest

web.webViewClient = object : WebViewClient(){

            override fun shouldInterceptRequest(
                view: WebView?,
                request: WebResourceRequest?
            ): WebResourceResponse? {
                var url = request?.url.toString()
                if(url.endsWith(".png") || url.endsWith(".jpg")){
                    val bytes = GlideUtil.syncLoad(url, "img")
                    if (bytes != null) {
                        return WebResourceResponse(
                            "image/*",
                            "utf-8",
                            ByteArrayInputStream(bytes)
                        )
                    }
                }
                if(url.endsWith(".html")){
                    val bytes = GlideUtil.syncLoad(url, "html")
                    if (bytes != null) {
                        return WebResourceResponse(
                            "text/html",
                            "utf-8",
                            ByteArrayInputStream(bytes)
                        )
                    }
                }
                return super.shouldInterceptRequest(view, request)
            }
        }

测试搞起来

1.第一次联网加载后,去缓存目录查看:

dsdsd.png

这里面应该包含了图片及html源文件吧。

2.杀进程,断网后,再次打开app,完美还原!!!

3.为了验证H5资源是使用了Glide缓存,将上图中的文件拷出,尝试一下重名名

1213123213.png

这些不就是H5所有的东西了嘛。

有的人要说有些H5里有视频,我想只要把视频当作file来处理,同样是可行的吧。待验证.......

附上 Glide 4.+ 设置缓存路径,便于后期维护本地资源

class App :Application() {
    companion object{
        lateinit var instance:Application
    }

    override fun onCreate() {
        super.onCreate()
        instance = this
        initGlide()
    }

    fun initGlide(){
        val builder = GlideBuilder()
        //设置内存缓存大小为20mb
        val memoryCacheSize = 1024 * 1024 * 200 // 200M
        //设置内存缓存大小
        builder.setMemoryCache(LruResourceCache(memoryCacheSize.toLong()))
        //设置硬盘缓存大小为1G
        val diskCacheSize = 1024 * 1024 * 1000 // 1G
//        builder.setDiskCache(InternalCacheDiskCacheFactory(this, "Glide_Cache", diskCacheSize.toLong()))
        builder.setDiskCache(DiskLruCacheFactory(cacheDir.path + "/Glide_Cache_Folder", diskCacheSize.toLong()))

        Glide.init(this, builder)
    }
}

笔记

通过 oss请求码获取视频第一帧画面

https://xxxxxxxxxx.mp4?x-oss-process=video/snapshot,t_1000,f_jpg,w_750
上一篇下一篇

猜你喜欢

热点阅读