之前在写下载APK的代码,okhttp的方式下载,本地写入用的用的RandomAccessFile.
发现类似的app网络速度比我快不少.
后来查看,除了发现一些逻辑错误,还是找到了根本原因:RandomAccessFile每次写入都要访问磁盘,速度太慢了.跟不上4G的步伐.
于是找到了BufferedRandomAccessFile的网上示例.
放到了我的code里面.
public void write(int b) throws IOException { if (this.curr_ >= this.hi_) { if (this.hitEOF_ && this.hi_ < this.maxHi_) { // at EOF -- bump "hi" this.hi_++; } else { // slow path -- write current buffer; read next one this.seek(this.curr_); if (this.curr_ == this.hi_) { // appending to EOF -- bump "hi" this.hi_++; } } } this.buff_[(int) (this.curr_ - this.lo_)] = (byte) b; this.curr_++; this.dirty_ = true; syncNeeded_ = true; }
它是具有缓存作用的RandomAccessFile, 满足断点续传的同时,大大了提高了效率.
后来在实践过程中,发现无奈的是,超过256M的下载是无法用BufferedRandomAccesssFile实例化的,会内存溢出.BufferedRandomA
ccessFile提高了速度根本原因是通过FileChannel和MappedByteBuffer的一起使用,利用了缓存.
在网友的文章里面,找到了
RandomAccessFile也能和FileChannel以及MappedByteBuffer一起,于是尝试放弃BufferedRandomAccessFile.
直接用RandomAccessFiles,代码如下:
private RandomAccessFile/*BufferedRandomAccessFile*/ mDownLoadFile; FileChannel channelOut = null; MappedByteBuffer mappedBuffer = null;
// 获得下载保存文件 mDownLoadFile = new RandomAccessFile(filepath, FILE_MODE); // Chanel NIO中的用法,由于RandomAccessFile没有使用缓存策略,直接使用会使得下载速度变慢, channelOut = mDownLoadFile.getChannel(); // 使用缓存下载,在这里指定下载位置。 mappedBuffer = channelOut.map(FileChannel.MapMode.READ_WRITE, completedSize, responseBody.contentLength()); ......
mappedBuffer.put(buffer, 0, length);
放弃了RandonmAccessFiles的seek和write方法.
最终实现了预期效果.
参考:
https://blog.csdn.net/hpb21/article/details/51270873
https://blog.csdn.net/silentbalanceyh/article/details/5252285