YCDownloader下载库(多线程、多任务、多进程)

3,272 阅读3分钟

0x01 前言

之前在我的文章《Android高速下载器实现思路——单个任务的提速与优化》提到了一些下载器的实现方式。然后因为这学期实验报告超级多,这个项目一鸽再鸽到现在基本成型了,做成了Android Library上传到了Jitpack。

项目传送门

欢迎下载sample体验、start。

0x02 集成

根目录的build.gradle

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

在module的build.gradle中:

dependencies {
    implementation 'com.github.SirLYC:YC-Downloader:latest.release'
}

Application中:

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        // multi process
        YCDownloader.install(this, true)
        // single process
        //        YCDownloader.install(this, false);
        // or
        //        YCDownloader.install(this);
    }
}

到这里就已经启动了下载服务。下载服务是和Application Context绑定的,目前暂未提供退出服务的接口。

0x03 使用

所有的接口都通过YCDownloader的静态方法导出,接口要么通过方法名就可以知道功能要么有相应的文档注释说明。

文件传送门

如果还不清楚,项目中有一个现成的sample,涵盖了这个库常见的一些API的使用(作为纯粹的HTTP下载器,功能应该还算比较完整)。

sample传送门

需要注意的地方是,如果使用多线程,最好不要有其他组建运行在:yc_downloader进程,这个进程在库的Manifest已经注册为了远程下载服务运行的进程。

0x04 有关上一篇文章的实际实现改进

上一篇文章中有提到把读和写的线程分离,按照读、写线程n:1的方式组织。实际上在之前实现时,这样的方法最后达到的下载效率并不是很高。

首先需要知道的是,读写线程分离确实能提升下载的速度,但是,读写线程比是一个重要的参数。在几次实验后发现,当读写线程为n:1时,读线程经常会被写线程拖慢,因为写线程只有一个,要处理多个线程下载下来的缓冲区的读。写完一个缓冲区后才能释放给某个读线程下载,并且还要被多个读线程竞争。

因此,改变这种局面的方式,一个是减小读写线程比(增多写线程),另一个是使用双缓冲(理论上缓冲区可以适量继续增加,但一般双缓冲足够了,一个写一个读循环使用,毕竟空间有开销)。最后在实现中,采用的是每个读线程对应一个写线程,并且有两个缓冲区

最后通过这种方式测试,下载速度基本可以跑满带宽。

0x05 后续维护/新功能

  • 如果有必要,添加退出服务的功能。
  • 对于下载文件的完整性校验。或者说检查下载文件相比于上一次下载是否过期(断点续传时)。
  • API可能需要调整的更加易于使用。目前很多API因为IPC的关系不能直接在主线程使用,需要异步的方式,后续可能会通过一些方式调整。
  • 如果有精力,可以试着添加其他协议的下载,比如非常常见的FTP下载。
  • 下载引擎部分基本已经成型,后续会基于当前版本的sample开发一个功能完整的下载器(有上架商店的想法)。