文件下载进度、文件上传进度、zip解压进度似乎在常见的app中很常见,进度值是怎么算出来的呢,原理再简单不过,进度=当前已传输大小/总大小。
如果算进度的代码写在业务中感觉不是太美观,也违背了解耦思路,毕竟进度计算是个很单一的功能,今天把以前写过的ProgressAwareInputStream
(对应下载)和ProgressAwareOutputStream
(对应上传)2个小东西拿出来溜溜:把进度计算融入Stream内部仅以listener告知进度情况。
/** * Interface for classes that want to monitor this stream */public interface OnProgressListener { /** * This callback should only be used to alert user download failed. */ void onError(String errorMsg); /** * This callback should only be used to update download progress UI * @param percentage download progress */ void onProgress(int percentage); /** * This callback should be used to do like open downloaded file. */ void onCompleted(); }
这是进度回调,很明确告知了传输进度、错误(及原因)、传输结束。
public class ProgressAwareInputStream extends InputStream { private InputStream inputStream; private long fileSize; private long localSize; private long lastPercent; private OnProgressListener listener; public ProgressAwareInputStream(InputStream in, long fileSize, long localSize) { this.inputStream = in; this.fileSize = fileSize; this.localSize = localSize; // init progress this.lastPercent = (int) (this.localSize * 100 / this.fileSize); } public void setOnProgressListener(OnProgressListener listener) { this.listener = listener; } @Override public int read() { try{ int readCount = inputStream.read(); localSize += readCount; checkProgress(); return readCount; } catch (IOException e) { e.printStackTrace(); listener.onError(e.getMessage()); return -1; } } @Override public int read(@NonNull byte[] b) { try{ int readCount = inputStream.read(b); localSize += readCount; checkProgress(); return readCount; } catch (IOException e) { e.printStackTrace(); listener.onError(e.getMessage()); return -1; } } @Override public int read(@NonNull byte[] b, int offset, int length) { try{ int readCount = inputStream.read(b, offset, length); localSize += readCount; checkProgress(); return readCount; } catch (IOException e) { e.printStackTrace(); listener.onError(e.getMessage()); return -1; } } private void checkProgress() { int percent = (int) (localSize * 100 / fileSize); // check whether progress is updated if (percent - lastPercent >= 1) { lastPercent = percent; if (listener != null){ listener.onProgress(percent); } } // check whether download is completed if(percent == 100 && listener != null){ listener.onCompleted(); } } @Override public void close() { try{ inputStream.close(); } catch (IOException e) { e.printStackTrace(); listener.onError(e.getMessage()); } } @Override public int available(){ try{ return inputStream.available(); } catch (IOException e) { e.printStackTrace(); listener.onError(e.getMessage()); return -1; } } @Override public void mark(int readlimit) { inputStream.mark(readlimit); } @Override public synchronized void reset() { try{ inputStream.reset(); } catch (IOException e) { e.printStackTrace(); listener.onError(e.getMessage()); } } @Override public boolean markSupported() { return inputStream.markSupported(); } @Override public long skip(long n){ try{ return inputStream.skip(n); } catch (IOException e) { e.printStackTrace(); listener.onError(e.getMessage()); return -1; } } }
思路很简单,就是override InputStream的内部所有影响进度的read()方法并把计算融入其中,有没有一种穿着狼皮的羊的感觉?
其实,ProgressAwareOutputStream也类似原理,就直接贴代码了:
public class ProgressAwareOutputStream extends OutputStream { private OutputStream outputStream; private long fileSize; private long uploadedSize; private long lastPercent; private OnProgressListener listener; public ProgressAwareOutputStream(OutputStream out, long fileSize, long uploadedSize){ this.outputStream = out; this.fileSize = fileSize; this.uploadedSize = uploadedSize; } public void setOnProgressListener(OnProgressListener listener) { this.listener = listener; } @Override public void write(int oneByte) throws IOException { try{ outputStream.write(oneByte); uploadedSize += 1; checkProgress(); } catch (IOException e) { e.printStackTrace(); listener.onError(e.getMessage()); } } @Override public void write(@NonNull byte[] buffer, int offset, int count) throws IOException { try{ outputStream.write(buffer, offset, count); uploadedSize += count; checkProgress(); } catch (IOException e){ listener.onError(e.getMessage()); } } @Override public void write(@NonNull byte[] buffer) throws IOException { try{ outputStream.write(buffer); uploadedSize += buffer.length; checkProgress(); }catch(IOException e){ listener.onError(e.getMessage()); } } @Override public void close() throws IOException { try{ outputStream.close(); }catch(IOException e){ listener.onError(e.getMessage()); } } public OutputStream getInnerOutputStream(){ return outputStream; } private void checkProgress() { int percent = (int) (uploadedSize * 100 / fileSize); // check whether progress is updated if (percent - lastPercent >= 1) { lastPercent = percent; if (listener != null){ listener.onProgress(percent); } } // check whether download is completed if(percent == 100 && listener != null){ listener.onCompleted(); } }
作者:生活简单些
链接:https://www.jianshu.com/p/91adb6deafe4
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦