編輯:關於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工具類
* 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);
}
LoginApi service=mApiManager.getApi(Config.baseUrl2,LoginApi.class); Map4.文件下載params = new HashMap<>(); params.put("file\"; filename=\""+file.getName()+"", RetrofitUtils.getRequestBody(file,context,callBack)); Call call= service.uploadImage(params);
LoginApi service=mApiManager.getApi(Config.baseUrl3,LoginApi.class,new ResponseProgressTransferCallback(context,callBack)); Callcall= service.downloadImage();
自定義控件三部曲之繪圖篇(十九)——LinearGradient與閃動文字效果
博主這段時間工作實在是太忙了,全天無尿點……博客一直沒更新,實在對不住大家……這篇就給大家講setShader的另
Android中View的滑動沖突——Android開發藝術探索筆記
介紹相信開發Android的人都會有這種體會:從網上下載的demo運行的好好的,但是只要出現了滑動沖突,Demo就無法正常工作了。但是不用擔心,解決滑動沖突有固定的模式,
Android上拉查看詳情實現
京東淘寶有那麼一種效果就是,上拉可以查看寶貝的詳情,這裡我也實現了一個類似的效果,也可以移植到商業項目上:先看看簡單的效果圖實現原理其實是利用了ScrollView的滾動
事件攔截機制分析
當Android系統捕獲到用戶的各種輸入事件後,如何准確地傳遞給真正需要這個事件的控件呢?Android給我們提供了一整套完善的事件傳遞、處理機制,來幫助開發者完成准確的