writeTo方法执行了多次
2019-03-18 本文已影响0人
夜丶丿迷茫
记录下最近遇到的一个问题,在写上传下载的工具类的时候出现一个错误unexpected end of stream;
发现错误后日常断点查看。结果发现在
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import java.io.File;
import java.io.IOException;
import io.reactivex.internal.schedulers.IoScheduler;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import okio.BufferedSink;
import okio.ForwardingSink;
import okio.Okio;
import okio.Sink;
/**
* @name lz
* @time 2019/3/4 17:39
*/
public class FileRequestBody<T> extends RequestBody {
public static final int UPDATE = 0x01;
/**
* 实体请求体
*/
private RequestBody requestBody;
/**
* 上传回调接口
*/
private BaseSubscriber<T> callback;
/**
* 包装完成的BufferedSink
*/
private BufferedSink bufferedSink;
/**
* 文件数量 用于多文件上传 单文件该值为1
*/
private int size = 1;
private MyHandler myHandler;
public FileRequestBody(RequestBody requestBody, BaseSubscriber<T> callback, File file) {
super();
this.requestBody = requestBody;
this.callback = callback;
// this.file = file;
if (myHandler == null)
myHandler = new MyHandler();
}
public FileRequestBody(RequestBody requestBody, BaseSubscriber<T> callback, File file, int size) {
super();
this.requestBody = requestBody;
this.callback = callback;
// this.file = file;
this.size = size;
if (myHandler == null)
myHandler = new MyHandler();
}
class MyHandler extends Handler {
//放在主线程中显示
public MyHandler() {
super(Looper.getMainLooper());
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE:
int progress = (int) msg.obj;
if (callback != null) callback.onLoading(progress);
break;
}
}
}
@Override
public long contentLength() throws IOException {
return requestBody.contentLength();
}
@Override
public MediaType contentType() {
return requestBody.contentType();
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
if (bufferedSink == null) {
//包装
bufferedSink = Okio.buffer(sink(sink));
}
//写入
requestBody.writeTo(bufferedSink);
//必须调用flush,否则最后一部分数据可能不会被写入
bufferedSink.flush();
bufferedSink=null;
}
/**
* 写入,回调进度接口
*
* @param sink
* @return
*/
private Sink sink(Sink sink) {
return new ForwardingSink(sink) {
//当前写入字节数
long bytesWritten = 0L;
//总字节长度,避免多次调用contentLength()方法
long contentLength = 0L;
@Override
public void write(Buffer source, long byteCount) throws IOException {
super.write(source, byteCount);
if (contentLength == 0) {
//获得contentLength的值,后续不再调用
contentLength = contentLength();
}
//增加当前写入的字节数
bytesWritten += byteCount;
//回调
int currProgress = (int) ((double) bytesWritten / (double) contentLength * 100);
Message msg = Message.obtain();
msg.what = UPDATE;
msg.obj = currProgress;
myHandler.sendMessage(msg);
}
};
}
}
writeTo方法居然被执行了两次,way? 然后就开始了各种百度,Google;终于是找到了原因
原来是在Http封装的时候 加入了日志拦截器 将Level 设置成了BODY 虽然还是没明白为啥 ;但是将BODY 修改成HEADERS 后完美的解决了问题 修改后的代码
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS); // 不要设置成BODY,会导致writeTo调用两次
有人知道原因的 欢迎留言探讨