美文网首页android问题记录
writeTo方法执行了多次

writeTo方法执行了多次

作者: 夜丶丿迷茫 | 来源:发表于2019-03-18 17:46 被阅读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调用两次
    

    有人知道原因的 欢迎留言探讨

    相关文章

      网友评论

        本文标题:writeTo方法执行了多次

        本文链接:https://www.haomeiwen.com/subject/byubmqtx.html