Android Retrofit实现多图片/文件、图文上传功能
什么是Retrofit?
Retrofit是Square开发的一个Android和Java的REST客户端库。这个库非常简单并且具有很多特性,相比其他的网络库,更容易让初学者快速掌握。它可以处理GET、POST、PUT、DELETE…等请求,还可以使用picasso加载图片。
一、再次膜拜下Retrofit
Retrofit无论从性能还是使用方便性上都很屌!!!,本文不去介绍其运作原理(虽然很想搞明白),后面会出专题文章解析Retrofit的内部原理;本文只是从使用上解析Retrofit实现多图片/文件、图文上传的功能。
二、概念介绍
1)注解@Multipart
从字面上理解就是与多媒体文件相关的,没错,图片、文件等的上传都要用到该注解,其中每个部分需要使用@Part来注解。。看其注释
/**
*Denotesthattherequestbodyismulti-part.Partsshouldbedeclaredasparametersand
*annotatedwith{@linkPart@Part}.
*/
2)注解@PartMap
当然可以理解为使用@PartMap注释,传递多个Part,以实现多文件上传。注释
/** *Denotesnameandvaluepartsofamulti-partrequest. **Valuesofthemaponwhichthisannotationexistswillbeprocessedinoneoftwoways: *
-
*
- Ifthetypeis{@linkokhttp3.RequestBodyRequestBody}thevaluewillbeused *directlywithitscontenttype. *
- Otherobjecttypeswillbeconvertedtoanappropriaterepresentationbyusing *{@linkplainConverteraconverter}. *
*
*@Multipart
*@POST("/upload")
*Callupload(
*@Part("file")RequestBodyfile,
*@PartMapMapparams);
*
**A{@codenull}valueforthemap,asakey,orasavalueisnotallowed. * *@seeMultipart *@seePart */
3)RequestBody
从上面注释中就可以看到参数类型是RequestBody,其就是请求体。文件上传就需要参数为RequestBody。官方使用说明如下http://square.github.io/retrofit/
MultipartpartsuseoneofRetrofit'sconvertersortheycanimplementRequestBodytohandletheirownserialization.
四、基本实现
了解了以上概念,下面就一一实现
1)接口定义
publicinterfaceIHttpService{
@Multipart
@POST("nocheck/file/agree.do")
CallupLoadAgree(@PartMapMapparams);
}
BaseBean是根据服务端返回数据进行定义的,这个使用时可以根据自有Server定义。
2)Retrofit实现
/**
*CreatedbyDELLon2017/3/16.
*上传文件用(包含图片)
*/
publicclassRetrofitHttpUpLoad{
/**
*超时时间60s
*/
privatestaticfinallongDEFAULT_TIMEOUT=60;
privatevolatilestaticRetrofitHttpUpLoadmInstance;
publicRetrofitmRetrofit;
publicIHttpServicemHttpService;
privateMapparams=newHashMap();
privateRetrofitHttpUpLoad(){
mRetrofit=newRetrofit.Builder()
.baseUrl(UrlConfig.ROOT_URL)
.client(genericClient())
.addConverterFactory(GsonConverterFactory.create())
.build();
mHttpService=mRetrofit.create(IHttpService.class);
}
publicstaticRetrofitHttpUpLoadgetInstance(){
if(mInstance==null){
synchronized(RetrofitHttpUpLoad.class){
if(mInstance==null)
mInstance=newRetrofitHttpUpLoad();
}
}
returnmInstance;
}
/**
*添加统一超时时间,http日志打印
*
*@return
*/
publicstaticOkHttpClientgenericClient(){
HttpLoggingInterceptorlogging=newHttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClienthttpClient=newOkHttpClient.Builder()
.addInterceptor(logging)
.connectTimeout(DEFAULT_TIMEOUT,TimeUnit.SECONDS)
.writeTimeout(DEFAULT_TIMEOUT,TimeUnit.SECONDS)
.readTimeout(DEFAULT_TIMEOUT,TimeUnit.SECONDS)
.build();
returnhttpClient;
}
/**
*将call加入队列并实现回调
*
*@paramcall调入的call
*@paramretrofitCallBack回调
*@parammethod调用方法标志,回调用
*@param泛型参数
*/
publicstaticvoidaddToEnqueue(Callcall,finalRetrofitCallBackretrofitCallBack,finalintmethod){
finalContextcontext=MyApplication.getContext();
call.enqueue(newCallback(){
@Override
publicvoidonResponse(Callcall,Responseresponse){
LogUtil.d("retrofitbackcode===="+response.code());
if(null!=response.body()){
if(response.code()==200){
LogUtil.d("retrofitbackbody===="+newGson().toJson(response.body()));
retrofitCallBack.onResponse(response,method);
}else{
LogUtil.d("toEnqueue,onResponseFail:"+response.code());
ToastUtil.makeShortText(context,"网络连接错误"+response.code());
retrofitCallBack.onFailure(response,method);
}
}else{
LogUtil.d("toEnqueue,onResponseFailm:"+response.message());
ToastUtil.makeShortText(context,"网络连接错误"+response.message());
retrofitCallBack.onFailure(response,method);
}
}
@Override
publicvoidonFailure(Callcall,Throwablet){
LogUtil.d("toEnqueue,onResponseFailunKnown:"+t.getMessage());
t.printStackTrace();
ToastUtil.makeShortText(context,"网络连接错误"+t.getMessage());
retrofitCallBack.onFailure(null,method);
}
});
}
/**
*添加参数
*根据传进来的Object对象来判断是String还是File类型的参数
*/
publicRetrofitHttpUpLoadaddParameter(Stringkey,Objecto){
if(oinstanceofString){
RequestBodybody=RequestBody.create(MediaType.parse("text/plain;charset=UTF-8"),(String)o);
params.put(key,body);
}elseif(oinstanceofFile){
RequestBodybody=RequestBody.create(MediaType.parse("multipart/form-data;charset=UTF-8"),(File)o);
params.put(key+"\";filename=\""+((File)o).getName()+"",body);
}
returnthis;
}
/**
*构建RequestBody
*/
publicMapbulider(){
returnparams;
}
}
其中定义了Retrofit实例、还用拦截器定义了统一的超时时间和日志打印;将call加入队列并实现回调。最重要的就是添加参数:
/***添加参数
*根据传进来的Object对象来判断是String还是File类型的参数
*/
publicRetrofitHttpUpLoadaddParameter(Stringkey,Objecto){
if(oinstanceofString){
RequestBodybody=RequestBody.create(MediaType.parse("text/plain;charset=UTF-8"),(String)o);
params.put(key,body);
}elseif(oinstanceofFile){
RequestBodybody=RequestBody.create(MediaType.parse("multipart/form-data;charset=UTF-8"),(File)o);
params.put(key+"\";filename=\""+((File)o).getName()+"",body);
}
returnthis;
}
这里就是根据传入的参数,返回不同的RequestBody。
3)使用
privatevoidupLoadAgree(){
showWaitDialog();
RetrofitHttpUpLoadretrofitHttpUpLoad=RetrofitHttpUpLoad.getInstance();
if(!StringUtil.isEmpty(pathImage[0])){
retrofitHttpUpLoad=retrofitHttpUpLoad.addParameter("pic1",newFile(pathImage[0]));
}
if(!StringUtil.isEmpty(pathImage[1])){
retrofitHttpUpLoad=retrofitHttpUpLoad.addParameter("pic2",newFile(pathImage[1]));
}
if(!StringUtil.isEmpty(pathImage[2])){
retrofitHttpUpLoad=retrofitHttpUpLoad.addParameter("zip",newFile(pathImage[2]));
}
Mapparams=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);
}
需要注意的是要对图片及文件路径进行判空操作,负责会报异常W/System.err:java.io.FileNotFoundException:/:openfailed:EISDIR(Isadirectory)
以上所述是小编给大家介绍的Android基于Retrofit实现多图片/文件、图文上传功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!