大型异步下载器(二):基于kotlin+Compose+协程+Flow+Channel+ OKhttp 实现多文件异步同时分片断点续传下载

实现一个多任务异步下载器,对于协程,线程,多任务理解,有很大帮助

一、前言

前一篇文章分享了大型异步下载器:基于kotlin+Compose+协程+Flow+Channel 实现多文件异步同时分片断点续传下载 实现的思路

本篇文章在之前的基础上:

  1. 做了代码优化,
  2. 加入了,初始化进度条,文件总长度的保存,
  3. 增加相关默认配置参数
  4. 增加下载实现,可选HttpURLConnection来实现,也可选Okhttp实现,也可自行定义其他的来实现
  5. UI可以不用compose

二、 初始化进度条,文件总长度的保存

  1. 断点续传,如果下载中途,断掉,或者手动暂停,下次来继续点击下载,从前面文章思路里面可以知道,我们每次下载之前,需要先从服务器获取到文件长度,然后更加文件长度来对文件进行分片下载。我们可以先如果我们第一次获取到了文件长度,中途中断,我们把文件长度保存起来,下次进去,便可以直接从本地读取文件长度。这样要快了一些。

  2. 如果第一次下载,不管是由于手动还是由于网络原因导致中断了,下一次进来,我们要立马看到下载按钮的进度条上次已经下载了多少,这个操作便是初始化下载进度。如果不保存文件总大小,我们只能再次获取到文件长度,才能计算出已经下载的部分的百分比,即便这样也要再次从服务端获取,如果我们是个下载列表,那样要同时去调用网络获取很多次才行。这样的设计肯定不行,所以我们把下载文件总长度保存起来,方便后面每次进入初始化计算进度立马就能UI展示出来。

  • 这里选择直接用一个文件保存起来,用它 RandomAccessFile 去写入。
  • RandomAccessFile有相关方法:
  • writeLong:用来保存文件总大小,
  • writeBoolean:用来保存下载文件是否支持断点续传,是否支持断点续传是看文件服务器上面是否支持,所以保存下来。
  • writeInt:用来保存单个文件下载的分片数量,前面文章有提到过,如果服务器上面要下载的文件大小,小于我们最小配置的分片大小,强制就用一个线程来下载。所以这块最终由获取文件大小之后来决定的。
  • writeLong:同时用它用来保存每个分片文件已经下载的开始位置,
  • 这里需要对RandomAccessFile有相关理解
    以下是RandomAccessFile可以读写的几种基本数据类型以及它们在文件中的字节表示大小:
  1. byte (readByte(), writeByte(int)):1个字节。
  2. boolean (readBoolean(), writeBoolean(boolean)):1个字节,但在文件中以0(false)或1(true)表示。
  3. char (readChar(), writeChar(int)):2个字节,使用Unicode编码。
  4. short (readShort(), writeShort(int)):2个字节。
  5. int (readInt(), writeInt(int)):4个字节。
  6. long (readLong(), writeLong(long)):8个字节。
  7. float (readFloat(), writeFloat(float)):4个字节。
  8. double (readDouble(), writeDouble(double)):8个字节。

我们用一个临时文件来存取:

writeLong先存long型文件大小(8个字节),

再用writeBoolean存取Boolean来存取文件是否支持断点续传(1个字节),

再用writeInt来存取Int(4个字节)单个文件分片数量,

如果我们分2片来存取每片已经下载到的位置,

那么第一片存取时候需要先移动到(13+8X0)位置 (tempFile.seek(13L + 8 * i)

那边第二篇存取时候需要先移动到(13+8X1)位置 (tempFile.seek(13L + 8 * i)

三、增加相关默认配置参数

  • 默认配置最大同时下载文件数:3
  • 断点续传分片最小大小,小于它没有必要分片 :1024 * 1024 * 1L
  • 断点续传分片最小大小,最小下载了100k才更新进度:1024 * 100 * 1L

四、使用方法:

1、repositories中添加如下maven

rust 复制代码
   repositories {
        maven { url 'https://repo1.maven.org/maven2/' }
        maven { url 'https://s01.oss.sonatype.org/content/repositories/releases/' }
    }
}

2、 dependencies中添加依赖

scss 复制代码
implementation("io.github.wgllss:Wgllss-Download:1.0.01")

3、viewModel中使用

  • 初始化 最大并行同时下载文件个数
  • 监听文件下载状态 及下载进度
  • 初始化上次没有下载完的文件下载进度
csharp 复制代码
/** 初始化 最大并行同时下载文件个数 **/
downloadManager.downloadInit(viewModelScope, 3)

/** 监听文件下载状态 及下载进度 **/
downloadManager.downloadStatusFlow().onEach {
    when (it) {
        is WXState.None -> {

        }

        is WXState.Downloading -> {
            _datas.value!![it.which].progress.value = it.progress
        }

        is WXState.Pause -> {}
        is WXState.Failed -> {}
        is WXState.Succeed -> {
            _datas.value!![it.which].progress.value = 100f
        }

        is WXState.Waiting -> {}
    }
}.launchIn(viewModelScope)

/** 初始化上次没有下载完的文件下载进度 **/
downloadDatas.forEachIndexed { index, url ->
    var fileSaveName = url.substring(url.lastIndexOf("?") + 1, url.length)
       downloadManager.initTempFilePercent(viewModelScope, index, strDownloadDir, fileSaveName)
}

4、下载调用 which:代表下载的那一个url,通常为下载列表中的位置

kotlin 复制代码
fun download(which: Int) {
    val url = downloadDatas[which]
    var fileSaveName = url.substring(url.lastIndexOf("?") + 1, url.length)
    if (which == 0) fileSaveName = "blue.apk"
    val fileAsyncNumb = 2
    downloadManager.download(viewModelScope, which, url, strDownloadDir, fileSaveName, fileAsyncNumb, true)
}

五、总结

本篇文章重点介绍了:之前的基础上:

  1. 做了代码优化,
  2. 加入了,初始化进度条,文件总长度的保存,
  3. 增加相关默认配置参数
  4. 增加下载实现,可选HttpURLConnection来实现,也可选Okhttp实现,也可自行定义其他的来实现
  5. UI可以不用compose

github地址
gitee地址

感谢阅读:

欢迎用你发财的小手 关注,点赞、收藏

这里你会学到不一样的东西

相关推荐
楼台的春风1 小时前
【Linux驱动开发 ---- 2.1_深入理解 Linux 内核架构】
linux·c++·人工智能·驱动开发·嵌入式硬件·ubuntu·架构
code bean1 小时前
【C#】 C#中 nameof 和 ToString () 的用法与区别详解
android·java·c#
掘金-我是哪吒1 小时前
分布式微服务系统架构第150集:JavaPlus技术文档平台日更
分布式·微服务·云原生·架构·系统架构
Edingbrugh.南空2 小时前
Kafka分区机制深度解析:架构原理、负载均衡与性能优化
架构·kafka·负载均衡
佛系小嘟嘟2 小时前
Android Studio Jetpack Compose毛玻璃特效按钮
android·ide·android studio
技术管理修行2 小时前
【二】主流架构模式深度对比:单体、前后端分离与微服务
微服务·云原生·架构·服务发现·前后端分离·单体架构
喝拿铁写前端3 小时前
前端批量校验还能这么写?函数式校验器组合太香了!
前端·javascript·架构
用户2018792831674 小时前
MagiskHidePropsConf 原理与实战故事
android
whysqwhw4 小时前
Egloo 项目结构分析
android