【Android】线程下载资源保证资源到位采用了 OkHttp的三方网络下载 & 文件缓存策略

2023-09-22 11:52:24

背景

使用 SVGA的三方的url播放方式会比较慢,至少延迟3s以上才会出现svga效果,所以改变策略:将线上的svga全部下载到本地进行播放,那么就得将采用网络缓存的方式实现效果。
在这里插入图片描述

实现

那么就得实现以下几点:

  • 初次下载
  • 缓存
  • 判重下载

下载的地址就放在这里。这里也是常规的文件路径下载

在这里插入图片描述

通过上下文类获取即可,如果参数路径没有,就会再构建一个新的路径下载。
整理的代码如下:

  // 获取当前的animation 文件夹
        String cacheDir = context.getExternalFilesDir(getAnimFilesName()).getAbsolutePath();

        // 挂个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 循环当前的礼物svag 获取
                for (GiftInfo giftInfo : giftInfoList) {
                    /**
                     * 名称规则
                     * 纯 id 加 文件后缀
                     */
                    String name = giftInfo.getId() + ".svga";
                    File svgaFile = new File(cacheDir, name);
                    // 判断去重
                    if (svgaFile.exists()) {
                        Log.i(TAG, "svgaFile.exists" + svgaFile.getAbsolutePath());
                        continue;
                    }

                    // 网络下载
                    Request request = new Request.Builder()
                            .url(giftInfo.getSvga())
                            .build();

                    APIBase.OkHttpInstance.getInstance().newCall(request).enqueue(new Callback() {
                        @Override
                        public void onFailure(@NonNull Call call, @NonNull IOException e) {
                            Log.e(TAG, "svgaFile donwload onFailure" + e.getMessage());
                            // 下载失败的处理
                            giftInfoList.remove(giftInfo);
                        }

                        @Override
                        public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                            if (response.isSuccessful()) {
                                // 将 SVGA 文件保存到缓存目录中
                                FileOutputStream outputStream = new FileOutputStream(svgaFile);
                                outputStream.write(response.body().bytes());
                                outputStream.close();
                                Log.i(TAG, "svgaFile donwload onResponse" + response.message());
                                // 下载成功后,处理逻辑
                            } else {
                                // 下载失败的处理
                                pLog.e(TAG, "svgaFile donwload onResponse" + response.message());
                                giftInfoList.remove(giftInfo);
                            }
                        }
                    });
                }
            }
        }).start();
  • 文件存储路径
String cacheDir = context.getExternalFilesDir(getAnimFilesName()).getAbsolutePath();
String name = giftInfo.getId() + ".svga";
File svgaFile = new File(cacheDir, name);
  • 判重下载
// 在for 循环下:
					 /**
                     * 名称规则
                     * 纯 id 加 文件后缀
                     */
                    String name = giftInfo.getId() + ".svga";
                    File svgaFile = new File(cacheDir, name);
                    // 判断去重
                    if (svgaFile.exists()) {
                        Log.i(TAG, "svgaFile.exists" + svgaFile.getAbsolutePath());
                        continue;
                    }
  • 网络下载

走okhttp的三方,并通过字节码转化为对应的文件

 APIBase.OkHttpInstance.getInstance().newCall(request).enqueue(new Callback() {
                        @Override
                        public void onFailure(@NonNull Call call, @NonNull IOException e) {
                            Log.e(TAG, "svgaFile donwload onFailure" + e.getMessage());
                            // 下载失败的处理
                            giftInfoList.remove(giftInfo);
                        }

                        @Override
                        public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                            if (response.isSuccessful()) {
                                // 将 SVGA 文件保存到缓存目录中
                                FileOutputStream outputStream = new FileOutputStream(svgaFile);
                                outputStream.write(response.body().bytes());
                                outputStream.close();
                                Log.i(TAG, "svgaFile donwload onResponse" + response.message());
                                // 下载成功后,处理逻辑
                            } else {
                                // 下载失败的处理
                                pLog.e(TAG, "svgaFile donwload onResponse" + response.message());
                                giftInfoList.remove(giftInfo);
                            }
                        }
                    });
                }
            }
        }).start();

待优化 线程使用

毕竟这个是挂线程的方式,没有在项目中用到更加稳定的线程处理方式。这是整个的一个遗憾。
所以下面我提供一个思路:可以阅读一下雪峰大佬的文字:
线程池的使用

  // 挂个线池
        ExecutorService service = Executors.newFixedThreadPool(10);
        // 循环当前的礼物svag 获取
        for (GiftInfo giftInfo : giftInfoList) {
            /**
             * 名称规则
             * 纯 id 加 文件后缀
             */
            String name = giftInfo.getId() + ".svga";
            File svgaFile = new File(cacheDir, name);
            if (svgaFile.exists()) {
                Log.i(TAG, "svgaFile.exists" + svgaFile.getAbsolutePath());
                continue;
            }
            service.execute(new Runnable() {
                @Override
                public void run() {
                    // 网络下载
                    Request request = new Request.Builder()
                            .url(giftInfo.getSvga())
                            .build();

                    WendyAPIBase.OkHttpInstance.getInstance().newCall(request).enqueue(new Callback() {
                        @Override
                        public void onFailure(@NonNull Call call, @NonNull IOException e) {
                            Log.e(TAG, "svgaFile donwload onFailure" + e.getMessage());
                            // 下载失败的处理
                            giftInfoList.remove(giftInfo);
                        }

                        @Override
                        public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                            if (response.isSuccessful()) {
                                // 将 SVGA 文件保存到缓存目录中
                                FileOutputStream outputStream = new FileOutputStream(svgaFile);
                                outputStream.write(response.body().bytes());
                                outputStream.close();
                                Log.i(TAG, "svgaFile donwload onResponse" + response.message());
                                // 下载成功后,处理逻辑
                            } else {
                                // 下载失败的处理
                                Log.e(TAG, "svgaFile donwload onResponse" + response.message());
                                giftInfoList.remove(giftInfo);
                            }
                        }
                    });
                }
            });

        }
        // 记得关闭
        service.shutdown();

效果如下:
还行~
在这里插入图片描述

更多推荐

【启发式搜索】

运用启发式策略的两种基本情况:(1)一个问题由于存在问题陈述和数据获取的模糊性,可能会使它没有一个确定的解。(2)虽然一个问题可能有确定解,但是其状态空间特别大,搜索中生成扩展的状态数会随着搜索的深度呈指数级增长。启发式信息用来简化搜索过程有关具体问题领域的特性的信息叫做启发信息。估价函数估价函数(evaluation

Linux命令教程:使用cat命令查看和处理文件

文章目录教程:使用cat命令在Linux中查看和处理文件1.引言2.cat命令的基本概述3.查看文件内容4.创建文件5.文件重定向和管道6.格式化和编辑文件7.实际应用示例7.1使用cat命令浏览日志文件7.2利用cat命令合并多个配置文件7.3使用cat命令将文件内容发送到其他命令进行处理8.注意事项和常见问题9.结

设计模式:备忘录模式

目录组件代码示例源码中使用优缺点总结备忘录模式(MementoPattern)是一种行为型设计模式,用于在不破坏封装性的前提下,捕获和恢复对象的内部状态。备忘录模式可以将对象的状态保存到备忘录对象中,并在需要时从备忘录对象中恢复状态,实现对象状态的保存和回滚。组件在备忘录模式中,通常包含以下角色:发起人(Origina

[X3m]ros交叉编译

ros需要安装以下包PYTHON_PACKAGE_LIST="larklark-parsernetifacespyyamlifcfgpyunicodedata"TogetheROS.Bot|TogetheROS.Bot用户手册编译tros.b​1使用docker文件​该部分操作均在开发机的docker内完成。##创建目

数据驱动 vs 关键字驱动:对搭建UI自动化测试框架的探索

UI自动化测试用例剖析让我们先从分析一端自动化测试案例的代码开始我们的旅程。以下是我之前写的一个自动化测试的小Demo。这个Demo基于Selenium与Java。由于现在Selenium在自动化测试的统治地位,并且随着Selenium4的即将发布,在未来很长的一段时间里这种统治地位应该还会持续,所以我的这篇文章还都是

我的创作纪念日

机缘第一次写博客我记得是写了个原生ajax的文章,因为突然用这个确实写不出来我写博客纯属为了记录项目经验有的bug可能这个项目解决了下个项目又噶了哈哈,我觉得跟博友们好好交流一下还是可以的,互相进步收获获得了88粉丝的关注有些文章的阅读量还是很高的,嘿嘿,收获最大的就是在工作中遇到的bug解决的更快了哈哈认识十几个志同

算法分享三个方面学习方法(做题经验,代码编写经验,比赛经验)

目录0.前言:(遇到OI不要慌)(只要道路对了,就不怕遥远)1.做题经验谈1.1做题的目的1.2我对于算法比赛的题目的看法1.2.1类似题1.2.2套模型:1.3在训练过程中如何做题1.4一些建议:提高算法能力1.5一些建议:提高代码能力1.6选一个好的OJ1.7分析问题的方法:我的一些经验2.代码编写经验谈2.1你5

UML活动图

在UML中,活动图本质上就是流程图,它描述系统的活动、判定点和分支等,因此它对开发人员来说是一种重要工具。活动图活动是某件事情正在进行的状态,既可以是现实生活中正在进行的某一项工作,也可以是软件系统中某个类对象的一个操作。活动图和流程图的区别1、流程图着重描述处理过程,他的主要控制结构是顺序、分支和循环,各个处理过程之

java学习--day11(抽象类、接口)

文章目录day10作业今天的内容1.super关键字2.抽象类【重要】2.1abstract关键字3.final关键字4.接口【重要】4.1生活中的接口4.2Java中接口4.3案例4.4案例day10作业1.成员变量和局部变量的区别成员变量:定义在类体中,整个类可以使用局部变量:定义在方法中,只能在方法使用2.继承的

系统架构设计师(第二版)学习笔记----信息安全系统及信息安全技术

【原文链接】系统架构设计师(第二版)学习笔记----信息加解密技术文章目录一、信息安全系统的组成框架1.1信息安全系统组成框架1.2信息安全系统技术内容1.3常用的基础安全设备1.4网络安全技术内容1.5操作系统安全内容1.6操作系统安全机制1.7数据库安全技术1.8信息安全系统的组织体系1.9信息安全系统的管理体系二

SocketTool V4.0 使用说明

TCP/UDPSocket调试工具提供了TCPServer,TCPClient,UDPServer,UDPClient,UDPGroup五种Socket调试方案。下面是一份简要的使用流程:TCP通信测试:1)创建TCPServer选中左方的TCPServer,然后点击”创建”按钮,软件弹出监听端口输入框。输入监听端口后

热文推荐