編輯:關於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 * @param2.設置文件上傳與下載的監聽方法* @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); } }
第一步:封裝一個的網絡回調方法
/** * 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();
博主這段時間工作實在是太忙了,全天無尿點……博客一直沒更新,實在對不住大家……這篇就給大家講setShader的另
介紹相信開發Android的人都會有這種體會:從網上下載的demo運行的好好的,但是只要出現了滑動沖突,Demo就無法正常工作了。但是不用擔心,解決滑動沖突有固定的模式,
京東淘寶有那麼一種效果就是,上拉可以查看寶貝的詳情,這裡我也實現了一個類似的效果,也可以移植到商業項目上:先看看簡單的效果圖實現原理其實是利用了ScrollView的滾動
當Android系統捕獲到用戶的各種輸入事件後,如何准確地傳遞給真正需要這個事件的控件呢?Android給我們提供了一整套完善的事件傳遞、處理機制,來幫助開發者完成准確的