Android Retrofit實(shí)現(xiàn)多圖片/文件、圖文上傳功能
什么是 Retrofit ?
Retrofit是Square開(kāi)發(fā)的一個(gè)Android和Java的REST客戶(hù)端庫(kù)。這個(gè)庫(kù)非常簡(jiǎn)單并且具有很多特性,相比其他的網(wǎng)絡(luò)庫(kù),更容易讓初學(xué)者快速掌握。它可以處理GET、POST、PUT、DELETE…等請(qǐng)求,還可以使用picasso加載圖片。
一、再次膜拜下Retrofit
Retrofit無(wú)論從性能還是使用方便性上都很!??!,本文不去介紹其運(yùn)作原理(雖然很想搞明白),后面會(huì)出專(zhuān)題文章解析Retrofit的內(nèi)部原理;本文只是從使用上解析Retrofit實(shí)現(xiàn)多圖片/文件、圖文上傳的功能。
二、概念介紹
1)注解@Multipart
從字面上理解就是與多媒體文件相關(guān)的,沒(méi)錯(cuò),圖片、文件等的上傳都要用到該注解,其中每個(gè)部分需要使用@Part來(lái)注解。。看其注釋
/**
* 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注釋?zhuān)瑐鬟f多個(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ù)類(lèi)型是RequestBody,其就是請(qǐng)求體。文件上傳就需要參數(shù)為RequestBody。官方使用說(shuō)明如下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)來(lái)的Object對(duì)象來(lái)判斷是String還是File類(lèi)型的參數(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)來(lái)的Object對(duì)象來(lái)判斷是String還是File類(lèi)型的參數(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);
} 需要注意的是要對(duì)圖片及文件路徑進(jìn)行判空操作,負(fù)責(zé)會(huì)報(bào)異常W/System.err: java.io.FileNotFoundException: /: open failed: EISDIR (Is a directory)
以上所述是小編給大家介紹的Android基于Retrofit實(shí)現(xiàn)多圖片/文件、圖文上傳功能,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Android開(kāi)發(fā)graphics?bufferqueue整體流程
這篇文章主要為大家介紹了Android開(kāi)發(fā)graphics?bufferqueue整體流程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
Android實(shí)現(xiàn)快遞物流時(shí)間軸效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)快遞物流時(shí)間軸效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05
Android 自定義底部上拉控件的實(shí)現(xiàn)方法
下面小編就為大家分享一篇Android 自定義底部上拉控件的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
android編程實(shí)現(xiàn)類(lèi)似于支付寶余額快速閃動(dòng)效果的方法
這篇文章主要介紹了android編程實(shí)現(xiàn)類(lèi)似于支付寶余額快速閃動(dòng)效果的方法,涉及Android時(shí)間函數(shù)的相關(guān)使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
Android中的SQL查詢(xún)語(yǔ)句LIKE綁定參數(shù)問(wèn)題解決辦法(sqlite數(shù)據(jù)庫(kù))
這篇文章主要介紹了Android中的SQL查詢(xún)語(yǔ)句LIKE綁定參數(shù)問(wèn)題解決辦法,本文使用的是sqlite數(shù)據(jù)庫(kù),需要的朋友可以參考下2014-06-06
Android開(kāi)發(fā)中應(yīng)用程序分享功能實(shí)例
這篇文章主要介紹了Android開(kāi)發(fā)中應(yīng)用程序分享功能,結(jié)合實(shí)例形式分析了基于Intent實(shí)現(xiàn)Android程序分享功能的技巧,需要的朋友可以參考下2016-02-02
Android 調(diào)用系統(tǒng)相冊(cè)選擇照片
這篇文章主要介紹了Android 調(diào)用系統(tǒng)相冊(cè)選擇照片的方法,幫助大家更好的進(jìn)行Android開(kāi)發(fā),感興趣的朋友可以了解下2020-12-12
Android實(shí)現(xiàn)懸浮可拖拽的Button
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)懸浮可拖拽的Button,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-06-06
ViewPager+RadioGroup實(shí)現(xiàn)左右滑動(dòng)卡片布局
這篇文章主要為大家詳細(xì)介紹了ViewPager+RadioGroup實(shí)現(xiàn)左右滑動(dòng)卡片布局,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02

