【Android】Retrofit的使用(3)-对Retrofit进行简单的封装


1.创建一个ApiMnanager类用来管理Retrofit的实例化操作

/**
 * Created by ccwant on 2016/9/6.
 */
public class ApiManager {
    private Context context;
    //网络缓存目录
    private File httpCacheDir ;
    //网络缓存大小
    private int cacheSize = 10 * 1024 * 1024; // 10 MiB
    //网络连接超时时间,单位/秒
    private int connTimeout=6;
    //网络缓存对象
    private Cache cache;
    //OkHttp
    private OkHttpClient client;
    public ApiManager(Context context){
        this.context=context;
    }

    /**
     * 初始化
     */
    private void initClient(){
        httpCacheDir=new File(context.getCacheDir(),"okhttp");
        cache= new Cache(httpCacheDir, cacheSize);
        //创建OkHttp
        client = new OkHttpClient();
        client.setConnectTimeout(connTimeout, TimeUnit.SECONDS);
        client.setCache(cache);
    }
    /**
     * 获取对应服务
     * @param service
     * @param <T>
     * @return
     */
    public <T> T getApi(String url,Class<T> service){
        return getApi(url,service,null);
    }
    /**
     * 获取对应服务
     * @param service
     * @param listener
     * @param <T>
     * @return
     */
    public <T> T getApi(String url,Class<T> service,ProgressResponseListener listener){
        initClient();
        if(listener!=null){
            client.interceptors().add(new DownloadProgressInterceptor(listener));
        }
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(url)//传递url
                .client(client)
                .addConverterFactory(JsonConverterFactory.create())//添加返回值解析器
                .build();
        return retrofit.create(service);
    }
}
2.设置文件上传与下载的监听方法

第一步:封装一个的网络回调方法

/**
 * Created by ccwant on 2016/8/19.
 * 网络通讯回调接口
 */
public interface OnHttpCallBack<T> {
    public void onSuccess(T entity);
    public void onFailure(Throwable t);
    public void onResponseProgress(long progress, long total, boolean done);
    public void onRequestProgress(long progress, long total, boolean done);
}
第二步:单独封装文件上传的监听方法

/**
 * 请求体进度回调接口,比如用于文件上传中
 * Created by ccwant on 2016/9/7.
 */
public interface ProgressRequestListener {
    void onProgress(long progress, long total, boolean done);
}

第三步:单独封装文件下载的监听方法

/**
 * Created by ccwant on 2016/9/7.
 */
public interface ProgressResponseListener {
    /**
     * @param progress     已经下载或上传字节数
     * @param total        总字节数
     * @param done         是否完成
     */
    void onProgress(long progress, long total, boolean done);
}
第四步:创建网络下载进度拦截器

/**
 * 网络下载进度拦截器
 * Created by ccwant on 2016/9/7.
 */
public class DownloadProgressInterceptor implements Interceptor {

    private String TAG="DownloadProgressInterceptor";
    private ProgressResponseListener listener;
    public DownloadProgressInterceptor(ProgressResponseListener listener){
        this.listener=listener;
    }
    @Override
    public Response intercept(Chain chain) throws IOException {
        Response orginalResponse = chain.proceed(chain.request());
        return orginalResponse.newBuilder().body(new ProgressResponseBody(orginalResponse.body(),listener)).build();
    }
}
第五步:包装请求体

/**
 * 包装的请求体,处理进度
 * Created by ccwant on 2016/9/7.
 */
public  class ProgressRequestBody extends RequestBody {
    //实际的待包装请求体
    private final RequestBody requestBody;
    //进度回调接口
    private final ProgressRequestListener progressListener;
    //包装完成的BufferedSink
    private BufferedSink bufferedSink;

    /**
     * 构造函数,赋值
     *
     * @param requestBody      待包装的请求体
     * @param progressListener 回调接口
     */
    public ProgressRequestBody(RequestBody requestBody, ProgressRequestListener progressListener) {
        this.requestBody = requestBody;
        this.progressListener = progressListener;
    }

    /**
     * 重写调用实际的响应体的contentType
     *
     * @return MediaType
     */
    @Override
    public MediaType contentType() {
        return requestBody.contentType();
    }

    /**
     * 重写调用实际的响应体的contentLength
     *
     * @return contentLength
     * @throws IOException 异常
     */
    @Override
    public long contentLength() throws IOException {
        return requestBody.contentLength();
    }

    /**
     * 重写进行写入
     *
     * @param sink BufferedSink
     * @throws IOException 异常
     */
    @Override
    public void writeTo(BufferedSink sink) throws IOException {
        if (bufferedSink == null) {
            //包装
            bufferedSink = Okio.buffer(sink(sink));
        }
        //写入
        requestBody.writeTo(bufferedSink);
        //必须调用flush,否则最后一部分数据可能不会被写入
        bufferedSink.flush();

    }

    /**
     * 写入,回调进度接口
     *
     * @param sink Sink
     * @return Sink
     */
    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;
                //回调
                progressListener.onProgress(bytesWritten, contentLength, bytesWritten == contentLength);
            }
        };
    }
}
第六步:包装返回体

/**
 * 包装的接收体,处理进度
 * Created by ccwant on 2016/9/7.
 */
public class ProgressResponseBody extends ResponseBody {

    //实际的待包装响应体
    private final ResponseBody responseBody;
    //进度回调接口
    private final ProgressResponseListener progressListener;
    //包装完成的BufferedSource
    private BufferedSource bufferedSource;

    /**
     * 构造函数,赋值
     * @param responseBody 待包装的响应体
     * @param progressListener 回调接口
     */
    public ProgressResponseBody(ResponseBody responseBody, ProgressResponseListener progressListener) {
        this.responseBody = responseBody;
        this.progressListener = progressListener;
    }


    /**
     * 重写调用实际的响应体的contentType
     * @return MediaType
     */
    @Override public MediaType contentType() {
        return responseBody.contentType();
    }

    /**
     * 重写调用实际的响应体的contentLength
     * @return contentLength
     * @throws IOException 异常
     */
    @Override public long contentLength() throws IOException {
        return responseBody.contentLength();
    }

    /**
     * 重写进行包装source
     * @return BufferedSource
     * @throws IOException 异常
     */
    @Override public BufferedSource source() throws IOException {
        if (bufferedSource == null) {
            //包装
            bufferedSource = Okio.buffer(source(responseBody.source()));
        }
        return bufferedSource;
    }

    /**
     * 读取,回调进度接口
     * @param source Source
     * @return Source
     */
    private Source source(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);
                //增加当前读取的字节数,如果读取完成了bytesRead会返回-1
                totalBytesRead += bytesRead != -1 ? bytesRead : 0;
                //回调,如果contentLength()不知道长度,会返回-1
                progressListener.onProgress(totalBytesRead, responseBody.contentLength(), bytesRead == -1);
                return bytesRead;
            }
        };
    }
}

第七步:创建Retrofit工具类

/**
 * Retrofit工具类
 * Created by ccwant on 2016/9/7.
 */
public class RetrofitUtils {

    /**
     * 获取RequestBody请求体
     * 主要用于文件上传
     * @param file 文件
     * @param callBack 网络回调
     * @return ProgressRequestBody
     */
    public static ProgressRequestBody getRequestBody(File file, Context context, OnHttpCallBack callBack){
        RequestBody requetBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
        return new ProgressRequestBody(requetBody,new RequestProgressTransferCallback(context,callBack));
    }

    /**
     * 获取RequestBody请求体
     * 主要用于文件上传
     * @param file 文件
     * @return RequestBody
     */
    public static RequestBody getRequestBody(File file){
        return RequestBody.create(MediaType.parse("multipart/form-data"), file);
    }

}
第八步:在之前封装的ApiManager中修改添加拦截器

 /**
     * 获取对应服务
     * @param service
     * @param listener
     * @param <T>
     * @return
     */
    public <T> T getApi(String url,Class<T> service,ProgressResponseListener listener){
        initClient();
        if(listener!=null){
            client.interceptors().add(new DownloadProgressInterceptor(listener));
        }
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(url)//传递url
                .client(client)
                .addConverterFactory(JsonConverterFactory.create())//添加返回值解析器
                .build();
        return retrofit.create(service);
    }

3.文件上传

LoginApi service=mApiManager.getApi(Config.baseUrl2,LoginApi.class);
Map<String, RequestBody> params = new HashMap<>();
params.put("file\"; filename=\""+file.getName()+"", RetrofitUtils.getRequestBody(file,context,callBack));
Call<JSONObject> call= service.uploadImage(params);
4.文件下载

 LoginApi service=mApiManager.getApi(Config.baseUrl3,LoginApi.class,new ResponseProgressTransferCallback(context,callBack));
Call<ResponseBody> call= service.downloadImage();






  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值