Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 【Android】Retrofit的使用(3)-對Retrofit進行簡單的封裝

【Android】Retrofit的使用(3)-對Retrofit進行簡單的封裝

編輯:關於Android編程

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 
     * @return
     */
    public  T getApi(String url,Class service){
        return getApi(url,service,null);
    }
    /**
     * 獲取對應服務
     * @param service
     * @param listener
     * @param 
     * @return
     */
    public  T getApi(String url,Class 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 {
    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 
     * @return
     */
    public  T getApi(String url,Class 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 params = new HashMap<>();
params.put("file\"; filename=\""+file.getName()+"", RetrofitUtils.getRequestBody(file,context,callBack));
Call call= service.uploadImage(params);
4.文件下載
 LoginApi service=mApiManager.getApi(Config.baseUrl3,LoginApi.class,new ResponseProgressTransferCallback(context,callBack));
Call call= service.downloadImage();
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved