android问题记录

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调用两次

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

上一篇下一篇

猜你喜欢

热点阅读