EventBus3.0 在高频任务下发送通知使用时遇到的问题
本人最近接手一个项目的bug修改,遇到一个当时非常有趣的问题。
我们在进行下载一个文件时,经常会使用到进度条,这很常见。但就是这个进度条在搞笑。
我在我的一加3手机上运行app进行下载的时候没有任何问题,但是在一个几百块的手机上下载文件时,进度条可能才到30%,但实际上文件已经下载完了。
/**内存缓存**/
byte[] buffer = new byte[1024];
/**保存文件的位置**/
File dFile = new File(....);
/**获取网络文件总大小,(方法名乱写的,实际api方法名可能不长这样)**/
long conLen = response.getContentLength();
/**以下载的大小**/
long dFileLen = 0;
while(../*读数据代码 io.read()*/..){
...
/**累加下载文件总大小**/
dFileLen += buffer.length() ;
/**通过EventBus发送进度**/
EventBus.getDefualt().post(new ProgressEvent(conLen,dFileLen));
...
}
可以看到,eventbus是在while里循环发送的通知
但是这个while是在线程中下载文件读数据的循环,循环一次的时间是多少?
这的看你的buffer是多大的、网速是多快的,我这里是1K的大小,下载速度是6M一秒。
忽略cpu、磁盘速率,那么一次循环的时间 1/6000*1000≈0.2毫秒…….加上cpu等影响可能在1ms就会循环一次
下载的文件大小是27M,那么总发的通知次数为27*1024 = 27648次 / 5s(时间保守估计)
这么高频的发送通知,并且还需要线程转换(工作线程 -> 主线程),eventbus(cpu)是吃不消的
所以发送在工作线程,处理在主线程,eventbus只能把消息押入队列慢慢搞。
就会导致反应迟钝。
但是在相对较好的手机上没问题,那是因为,CPU牛逼啊!
解决方法:
int filter = 0;
while(../*读数据代码 io.read()*/..){
...
if(++filter % 10 == 0)//过滤一下,别发那么频繁
EventBus.getDefualt().post(new ProgressEvent(conLen,dFileLen));
...
}
/*======OR======*/
byte[] buffer = new byte[1024*10]//或者增加buffer大小,也是减少发送次数