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

来源:互联网 发布:java 复杂网络软件包 编辑:程序博客网 时间:2024/05/18 18:54

不要在最需要奋斗的年纪选择了安逸!

在上一讲中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;    }}

效果图:

源码下载

原创粉丝点击