公司有一个项目有下载app的模块,这样的话下载操作就比较常用,平时我们的应用只有检查更新时才用到下载,所以app下载的操作多了就会想到优化一下,就写了一个多线程下载,我没有使用第三方封装好的一些下载库,正因为没有使用第三方下载库,所以才能多学到一点东西。
使用的网络请求是主流的OkHttp,通过阅读源码,可以知道OkHttp默认的超时时间是10秒,分3种情况,如下(OkHttpClient.Builder的构造函数):
public Builder() {
...
callTimeout = 0;
connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
...
}
今天项目上线了,发现下载的时候在低网速的时候经常断开,比如20K/s的网速,按道理说网速慢一点就慢一点,不应该断开啊,后来我把读写的超时时间设置为5秒,发我现在1M/s的网速下也会出现下载中断,因为我是5个线程同时下载,虽然网速不错,但是有的线程读数据的超时时间超过了5秒就导致下载中断了,我试了好几次,1M/s的网速下,几乎每次下载都会中断一次或两次(下载的app大小为28M),后来就找原因了,为什么网速1M每秒还会中断,通过SVN查看修改记录发现修改了超时时间,默认的时候是没有设置的反而没有出现问题,当我还原这个超时设置时问题就没有了,所以证明了是超时时间导致,了解了这个之后,我就修改了这些超时时间,连接服务器的速度一般比较快一些,而读取的速度会慢一些,所以连接的超时可以设置小一点,而读写的超时设置大一点,设置完之后,在20K/s的网速下下载文件,出现中断的次数明显比之前少的多了,如下:
// 就算网速慢,连接的到服务器的时间也是很快的,但是网速慢时读写的速度就会很慢,超时时间很有可能大于10秒的,所以读写时间尽量设置大一点。
// 就算网速达到1M/s,5个线程同时下也有可能有个别线程读流时超时超过10秒的,所以读写的超时时间要长一点
val okHttpClient: OkHttpClient = OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build()
公司测试说拿领导手机下载30 ~ 40K/s的网速,于是也模拟了一下30K的网速,发现下载一断时间后还是会有断开的,所以就把读写的超时改成60秒,问题解决,虽然说好像超时要等很久啊,其实5个线程下载,只是个别线程可能读不到东西而已,就有60秒的时间等待读到东西,但是别的线程是有读到东西的,所以看下载界面不会说网不好时会不会等60秒不动啊,不会的,除非网速为0。这种情况下虽然下载断开的问题解决了,但是由于网速慢,要下载完一个28M的apk那是要等很久的。