Retrofit(二)、使用Retrofit+OkHttp下载文件并带进度条

不要在最需要奋斗的年纪选择了安逸!
在上一讲中Retrofit(一)、Retrofit+OkHttp实现简单的Get与Post请求 中实现了用Retrofit实现简单的Get与post请求。下面我们用Retrofit实现文件下载与上传并带进度!可以参考这两篇博文:

OkHttp下载文件并带进度条
OkHttp上传文件到服务器并带进度

一、文件的下载

1.写下载接口
  public interface DownloadRetrofit{
        @GET("download/2.jpg")
        Call<ResponseBody> downloadFile();
    }
2.在RetrofitUtil类中增加一个下载的方法downloadFileProgress
 public static String baseUrl = "http://192.168.0.100:8080/OkHttpServer/";

   public static  Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
           .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
//            .addConverterFactory(ScalarsConverterFactory.create())
           .addConverterFactory(GsonConverterFactory.create())
           .baseUrl(baseUrl);


    private static OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(10000, TimeUnit.MILLISECONDS)
            .readTimeout(10000,TimeUnit.MILLISECONDS)
            .writeTimeout(10000,TimeUnit.MILLISECONDS).build();

  public static void downloadFileProgress( final ProgressListener listener,Callback<ResponseBody> callback){
    //okhttp拦截

        OkHttpClient client = okHttpClient.newBuilder().addNetworkInterceptor(new Interceptor() {
            @Override
            public okhttp3.Response intercept(Chain chain) throws IOException {
                okhttp3.Response response = chain.proceed(chain.request());
                return response.newBuilder().body(new ProgressResponseBody(response.body(),listener)).build();
            }
        }).build();


        InterfaceRetrofit.DownloadRetrofit downloadRetrofit = retrofitBuilder.client(client).build().create(InterfaceRetrofit.DownloadRetrofit.class);


        downloadRetrofit.downloadFile().enqueue(callback);


    }
上面代码中ProgressResponseBody代码如下:
public class ProgressResponseBody extends ResponseBody {
    public static final int UPDATE = 0x01;
    public static final String TAG = ProgressResponseBody.class.getName();
    private ResponseBody responseBody;
    private ProgressListener mListener;
    private BufferedSource bufferedSource;
    private Handler myHandler;
    public ProgressResponseBody(ResponseBody body, ProgressListener listener) {
        responseBody = body;
        mListener = listener;
        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:
                    ProgressModel progressModel = (ProgressModel) msg.obj;
                    if (mListener!=null)mListener.onProgress(progressModel.getCurrentBytes(),progressModel.getContentLength(),progressModel.isDone());
                    break;

            }
        }


    }

    @Override
    public MediaType contentType() {
        return responseBody.contentType();
    }

    @Override
    public long contentLength() {
        return responseBody.contentLength();
    }

    @Override
    public BufferedSource source() {

        if (bufferedSource==null){
            bufferedSource = Okio.buffer(mySource(responseBody.source()));
        }
        return bufferedSource;
    }

    private Source mySource(Source source) {

        return  new ForwardingSource(source) {
            long totalBytesRead = 0L;
            @Override
            public long read(Buffer sink, long byteCount) throws IOException {
                long bytesRead = super.read(sink, byteCount);
                totalBytesRead +=bytesRead!=-1?bytesRead:0;

                Message msg = Message.obtain();
                msg.what = UPDATE;
                msg.obj =  new ProgressModel(totalBytesRead,contentLength(),totalBytesRead==contentLength());
                myHandler.sendMessage(msg);
                Log.i(TAG,"currentBytes=="+totalBytesRead+"==contentLength=="+contentLength());
                return bytesRead;
            }
        };


    }
}
3.另外进度接口:
public interface ProgressListener {
    void onProgress(long currentBytes, long contentLength, boolean done);
}
ProgressModel实体类:
public class ProgressModel implements Parcelable {

    private long currentBytes;
    private long contentLength;
    private boolean done = false;

    public ProgressModel(long currentBytes, long contentLength, boolean done) {
        this.currentBytes = currentBytes;
        this.contentLength = contentLength;
        this.done = done;
    }

    public long getCurrentBytes() {
        return currentBytes;
    }

    public void setCurrentBytes(long currentBytes) {
        this.currentBytes = currentBytes;
    }

    public long getContentLength() {
        return contentLength;
    }

    public void setContentLength(long contentLength) {
        this.contentLength = contentLength;
    }

    public boolean isDone() {
        return done;
    }

    public void setDone(boolean done) {
        this.done = done;
    }

    private static final Creator<ProgressModel> CREATOR = new Creator<ProgressModel>() {
        @Override
        public ProgressModel createFromParcel(Parcel parcel) {
            return new ProgressModel(parcel);
        }

        @Override
        public ProgressModel[] newArray(int i) {
            return new ProgressModel[i];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeLong(currentBytes);
        parcel.writeLong(contentLength);
        parcel.writeByte((byte) (done==true?1:0));
    }

    protected ProgressModel(Parcel parcel) {
        currentBytes = parcel.readLong();
        contentLength = parcel.readLong();
        done = parcel.readByte()!=0;
    }
}
效果图:

源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值