您好,登錄后才能下訂單哦!
什么是 Retrofit ?
Retrofit是Square開發(fā)的一個(gè)Android和Java的REST客戶端庫。這個(gè)庫非常簡單并且具有很多特性,相比其他的網(wǎng)絡(luò)庫,更容易讓初學(xué)者快速掌握。它可以處理GET、POST、PUT、DELETE…等請求,還可以使用picasso加載圖片。
一、再次膜拜下Retrofit
Retrofit無論從性能還是使用方便性上都很屌?。?!,本文不去介紹其運(yùn)作原理(雖然很想搞明白),后面會出專題文章解析Retrofit的內(nèi)部原理;本文只是從使用上解析Retrofit實(shí)現(xiàn)多圖片/文件、圖文上傳的功能。
二、概念介紹
1)注解@Multipart
從字面上理解就是與多媒體文件相關(guān)的,沒錯(cuò),圖片、文件等的上傳都要用到該注解,其中每個(gè)部分需要使用@Part來注解。。看其注釋
/** * Denotes that the request body is multi-part. Parts should be declared as parameters and * annotated with {@link Part @Part}. */
2)注解@PartMap
當(dāng)然可以理解為使用@PartMap注釋,傳遞多個(gè)Part,以實(shí)現(xiàn)多文件上傳。注釋
/** * Denotes name and value parts of a multi-part request. * <p> * Values of the map on which this annotation exists will be processed in one of two ways: * <ul> * <li>If the type is {@link okhttp3.RequestBody RequestBody} the value will be used * directly with its content type.</li> * <li>Other object types will be converted to an appropriate representation by using * {@linkplain Converter a converter}.</li> * </ul> * <p> * <pre><code> * @Multipart * @POST("/upload") * Call<ResponseBody> upload( * @Part("file") RequestBody file, * @PartMap Map<String, RequestBody> params); * </code></pre> * <p> * A {@code null} value for the map, as a key, or as a value is not allowed. * * @see Multipart * @see Part */
3)RequestBody
從上面注釋中就可以看到參數(shù)類型是RequestBody,其就是請求體。文件上傳就需要參數(shù)為RequestBody。官方使用說明如下http://square.github.io/retrofit/
Multipart parts use one of Retrofit's converters or they can implement RequestBody to handle their own serialization.
四、基本實(shí)現(xiàn)
了解了以上概念,下面就一一實(shí)現(xiàn)
1)接口定義
public interface IHttpService { @Multipart @POST("nocheck/file/agree.do") Call<BaseBean> upLoadAgree(@PartMap Map<String, RequestBody>params); }
BaseBean是根據(jù)服務(wù)端返回?cái)?shù)據(jù)進(jìn)行定義的,這個(gè)使用時(shí)可以根據(jù)自有Server定義。
2)Retrofit實(shí)現(xiàn)
/** * Created by DELL on 2017/3/16. * 上傳文件用(包含圖片) */ public class RetrofitHttpUpLoad { /** * 超時(shí)時(shí)間60s */ private static final long DEFAULT_TIMEOUT = 60; private volatile static RetrofitHttpUpLoad mInstance; public Retrofit mRetrofit; public IHttpService mHttpService; private Map<String, RequestBody> params = new HashMap<String, RequestBody>(); private RetrofitHttpUpLoad() { mRetrofit = new Retrofit.Builder() .baseUrl(UrlConfig.ROOT_URL) .client(genericClient()) .addConverterFactory(GsonConverterFactory.create()) .build(); mHttpService = mRetrofit.create(IHttpService.class); } public static RetrofitHttpUpLoad getInstance() { if (mInstance == null) { synchronized (RetrofitHttpUpLoad.class) { if (mInstance == null) mInstance = new RetrofitHttpUpLoad(); } } return mInstance; } /** * 添加統(tǒng)一超時(shí)時(shí)間,http日志打印 * * @return */ public static OkHttpClient genericClient() { HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient httpClient = new OkHttpClient.Builder() .addInterceptor(logging) .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .build(); return httpClient; } /** * 將call加入隊(duì)列并實(shí)現(xiàn)回調(diào) * * @param call 調(diào)入的call * @param retrofitCallBack 回調(diào) * @param method 調(diào)用方法標(biāo)志,回調(diào)用 * @param <T> 泛型參數(shù) */ public static <T> void addToEnqueue(Call<T> call, final RetrofitCallBack retrofitCallBack, final int method) { final Context context = MyApplication.getContext(); call.enqueue(new Callback<T>() { @Override public void onResponse(Call<T> call, Response<T> response) { LogUtil.d("retrofit back code ====" + response.code()); if (null != response.body()) { if (response.code() == 200) { LogUtil.d("retrofit back body ====" + new Gson().toJson(response.body())); retrofitCallBack.onResponse(response, method); } else { LogUtil.d("toEnqueue, onResponse Fail:" + response.code()); ToastUtil.makeShortText(context, "網(wǎng)絡(luò)連接錯(cuò)誤" + response.code()); retrofitCallBack.onFailure(response, method); } } else { LogUtil.d("toEnqueue, onResponse Fail m:" + response.message()); ToastUtil.makeShortText(context, "網(wǎng)絡(luò)連接錯(cuò)誤" + response.message()); retrofitCallBack.onFailure(response, method); } } @Override public void onFailure(Call<T> call, Throwable t) { LogUtil.d("toEnqueue, onResponse Fail unKnown:" + t.getMessage()); t.printStackTrace(); ToastUtil.makeShortText(context, "網(wǎng)絡(luò)連接錯(cuò)誤" + t.getMessage()); retrofitCallBack.onFailure(null, method); } }); } /** * 添加參數(shù) * 根據(jù)傳進(jìn)來的Object對象來判斷是String還是File類型的參數(shù) */ public RetrofitHttpUpLoad addParameter(String key, Object o) { if (o instanceof String) { RequestBody body = RequestBody.create(MediaType.parse("text/plain;charset=UTF-8"), (String) o); params.put(key, body); } else if (o instanceof File) { RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data;charset=UTF-8"), (File) o); params.put(key + "\"; filename=\"" + ((File) o).getName() + "", body); } return this; } /** * 構(gòu)建RequestBody */ public Map<String, RequestBody> bulider() { return params; } }
其中定義了Retrofit實(shí)例、還用攔截器定義了統(tǒng)一的超時(shí)時(shí)間和日志打印;將call加入隊(duì)列并實(shí)現(xiàn)回調(diào)。最重要的就是添加參數(shù):
/** * 添加參數(shù) * 根據(jù)傳進(jìn)來的Object對象來判斷是String還是File類型的參數(shù) */ public RetrofitHttpUpLoad addParameter(String key, Object o) { if (o instanceof String) { RequestBody body = RequestBody.create(MediaType.parse("text/plain;charset=UTF-8"), (String) o); params.put(key, body); } else if (o instanceof File) { RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data;charset=UTF-8"), (File) o); params.put(key + "\"; filename=\"" + ((File) o).getName() + "", body); } return this; }
這里就是根據(jù)傳入的參數(shù),返回不同的RequestBody。
3)使用
private void upLoadAgree() { showWaitDialog(); RetrofitHttpUpLoad retrofitHttpUpLoad = RetrofitHttpUpLoad.getInstance(); if (!StringUtil.isEmpty(pathImage[0])){ retrofitHttpUpLoad = retrofitHttpUpLoad.addParameter("pic1",new File(pathImage[0])); } if (!StringUtil.isEmpty(pathImage[1])){ retrofitHttpUpLoad = retrofitHttpUpLoad.addParameter("pic2", new File(pathImage[1])); } if (!StringUtil.isEmpty(pathImage[2])){ retrofitHttpUpLoad = retrofitHttpUpLoad.addParameter("zip", new File(pathImage[2])); } Map<String, RequestBody> params = retrofitHttpUpLoad .addParameter("status", "4") .addParameter("pickupId", tv_orderquality_pid.getText().toString()) .addParameter("cause", reason) .addParameter("connectname", et_orderquality_lxrname.getText().toString()) .addParameter("connectphone", et_orderquality_lxrphone.getText().toString()) .addParameter("details", et_orderquality_xqms.getText().toString()) .bulider(); RetrofitHttpUpLoad.addToEnqueue(RetrofitHttpUpLoad.getInstance().mHttpService.upLoadAgree(params), this, HttpStaticApi.HTTP_UPLOADAGREE); }
需要注意的是要對圖片及文件路徑進(jìn)行判空操作,負(fù)責(zé)會報(bào)異常W/System.err: java.io.FileNotFoundException: /: open failed: EISDIR (Is a directory)
以上所述是小編給大家介紹的Android基于Retrofit實(shí)現(xiàn)多圖片/文件、圖文上傳功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對億速云網(wǎng)站的支持!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。