Retrofit2 简明教程一文档格式.docx
《Retrofit2 简明教程一文档格式.docx》由会员分享,可在线阅读,更多相关《Retrofit2 简明教程一文档格式.docx(12页珍藏版)》请在冰豆网上搜索。
version>
2.1.0<
/version>
/dependency>
PROGUARD
如果你正在使用PROGUARD在你的项目中添加以下代码到您的配置:
-dontwarnretrofit2.**
-keepclassretrofit2.**{*;
}
-keepattributesSignature
-keepattributesExceptions
最初的步骤
创建Retrofit实例
在使用Retrofit前,我们需要先创建Retrofit实例,并且做一系列配置,然而Retrofit设计的也是非常好,这些配置都是可插拔的:
Retrofitretrofit=newRetrofit.Builder()
//设置baseUrl,注意baseUrl应该以/结尾。
.baseUrl("
http:
//news-
//使用Gson解析器,可以替换其他的解析器
.addConverterFactory(GsonConverterFactory.create())
//设置OKHttpClient,如果不设置会提供一个默认的
.client(newOkHttpClient())
//.client(newUrlConnectionClient())
//.client(newApacheClient())
//.client(newCustomClient())
.build();
更换HTTPclient与Converter
Retrofit背后的HTTPclient,以及序列化机制(JSON/XML协议)等都是可以替换,因此你可以选择自己合适的方案。
Retrofit最早出来的时候,只支持Apache的HTTPclient。
后来增加了URLconnection,以及OkHttp的支持。
如果你想使用其他的HTTPclient,可以通过以下方式了替换,或者更改为自定义的HTTPclient:
//设置OKHttpClient,如果不设置会提供一个默认的OkHttpClient
序列化功能也是可替换的。
默认是用的GSON,你当然也可以用Jackson来替换掉。
//当需要返回原始String数据时
.addConverterFactory(ScalarsConverterFactory.create())
除此之外Retrofit还提供以下几种Converter:
Gson:
com.squareup.retrofit2:
converter-gson
Jackson:
converter-jackson
Moshi:
converter-moshi
Protobuf:
converter-protobuf
Wire:
converter-wire
SimpleXML:
converter-simplexml
Scalars(primitives,boxed,andString):
converter-scalars
基本使用
我们将看一下如何用Retrofit与服务器交互,通过它你将学会如何运用Retrofit于日常开发。
Retrofit使用接口,方法和参数,使用注解表明了请求将如何处理,每一种方法都必须有一个HTTP标注提供请求的方法和相对URL,有五种内置注解:
GET,POST,PUT,DELETE,和HEAD,在注解中指定URL。
请选择以下方式中合适的请求方式来处理您的请求。
GET
在这里我们最开始第一个GET请求使用的是知乎日报的api,为了更好使用Retrofit其他请求方式而又没有比较好的公开api,我自行编写了配合使用Retrofit的测试服务端,放置在外网以便大家测试使用。
普通GET
基于上面的最初的步骤,接下来我们需要定义一个接口,并且使用注解(@GET)表明一次GET请求:
publicinterfaceZhihuService{
//获取启动页大图
@GET("
start-image/1080*1776"
)
Call<
StartImageBean>
getStartImage();
}
这是一个普通的GET请求,接着我们来看如何利用Retrofit创建服务接口,并且设置参数:
ZhihuServicemessageService=retrofit.create(ZhihuService.class);
startImage=messageService.getStartImage();
最后,使用startImage.enqueue进行异步请求,并且获取了我们期待的数据(实体对象):
startImage.enqueue(newCallback<
(){
@Override
publicvoidonResponse(Call<
call,Response<
response){
if(response.isSuccessful()){
Log.d(TAG,response.body().toString());
resultTextView.setText("
"
+response.body().toString());
publicvoidonFailure(Call<
call,Throwablet){
+"
error:
+t.getMessage());
});
如果你想使用call.execute()进行同步请求,需要注意的是不要放在UI线程:
try{
Response<
response=call.execute();
//同步
Log.d(TAG,"
response:
}catch(IOExceptione){
e.printStackTrace();
因为一次call.execute()的request只能执行一次,否则你将会得到如下错误:
java.lang.IllegalStateException:
Alreadyexecuted
如果你想取消本次请求可以使用startImage.cancel()或者是复制一次request,再次请求:
startImage.cancel();
//取消
cloneRequsest=startImage.clone();
//复制
是不是感觉特别简单,使用时候只需调用接口,这一切都简化了我们的操作。
动态参数(GET)
我们需要先定义一个接口,并且使用注解(@Query)或者是@QueryMap表明动态参数请求如何处理:
相应的URL是这样:
//baseurl/app/test/sayHello?
username=fuchenxuan&
age=110
test/sayHello"
String>
sayHello(@Query("
username"
)Stringusername,@Query("
age"
)Stringage);
接着我们忽略接口的创建,直接使用Retrofit与服务器交互,值得注意的是我们此次返回的数据是String,而不是一个自定义的实体类对象。
所以我们需要更换Converter,否则你将会遇到不必要的麻烦(而我觉得Retrofit应该提供一个默认Stirng的实现):
接着我们就得到了我们期待的数据:
Call<
doubanCall=myTestApiService.sayHello("
fuchenxuan"
"
110"
);
doubanCall.enqueue(newCallback<
RESTful方式(动态PATH)
GET动态PATH就是优雅的RESTfulapi方式,
@GET("
start-image/{size}"
getStartImageByPath(@Path("
size"
)Stringsize);
POST
form-data(表单数据)
form-data就是如表单K-V参数形式
这里其实就跟GET的动态参数是一致的只是替换了@POST注解
publicinterfaceMyTestApiService{
@POST("
ResultBean>
postSayHello(@Query("
JSON参数(raw)
当服务器需要你POST参数以json打包数据格式请求时,然而这种参数方式RESTfulapi也是非常常见的,我们需要使用@Body注解:
@POST("
test/sayHi"
//@Headers("
Accept-Encoding:
application/json"
//使用@Headers可添加header
postSayHi(@BodyUserBeanuserBean);
上面我们还示例了如何使用@Headers@Headers("
)添加头部信息,或者我们有需求需要使用@Header实现动态头部信息:
@Headers("
//也可以使用@Header可添加header
postSayHi(@BodyUserBeanuserBean,@Header("
city"
)Stringcity);
前面也说了retrofit非常适用于RESTfulurl的格式,这里因为知乎的就是RESTfulapi,我们直接使用和GET动态URL一样的注解(@PATH)来表明请求处理:
文件上传
在我们开发当中肯定必不可少图片上传了,我们使用表单上传文件时,必须让<
form>
表单的enctyped等于multipart/form-data。
文件上传我们需要使用@MultiPart和@Part,MultiPart意思就是允许多个@Part多部分上传。
@Multipart
test/upload"
upload(@Part("
file\"
;
filename=\"
launcher_icon.png"
)RequestBodyfile);
值得注意的是我们需要在@Part指定file和filename的值,避免一些不必要的麻烦。
相应的我们在使用retrofit的时候,首先先获取到文件,并且创建RequestBody实例,然后调用接口请求,相应代码块如下:
Filefile=newFile(getExternalFilesDir(null),"
RequestBodyfileBody=RequestBody.create(MediaType.parse("
image/png"
),file);
doubanCall=myTestApiService.upload(fileBody);
//Log.d(TAG,response.body().toString());
大文件下载
文件下载我们需要使用@Url和@Streaming,@Url动态Url正好非常适合我们的场景,而使用@Streaming注解可以让我们下载非常大的文件时,避免Retrofit将整个文件读进内存,否则可能造成OOM现象。
声明接口如下:
@Streaming
@GET
ResponseBody>
downloadFileByDynamicUrlAsync(@UrlStringdownloadUrl);
需要注意的是我们需要使用Retrofitcall.execute同步获取ResponseBody,那么我们就需要放进一个单独的工作线程中:
newAsyncTask<
Void,Long,Void>
protectedVoiddoInBackground(Void...voids){
call=myTestApiService.downloadFileByDynamicUrlAsync(API_BASE_URL.concat("
/res/atom-amd64.deb"
));
try{
booleanwrittenToDisk=writeResponseBodyToDisk(response.body());
下载文件"
+writtenToDisk);
}catch(IOExceptione){
returnnull;
protectedvoidonPreExecute(){
super.onPreExecute();
}.execute();
最后我们需要将文件写入磁盘根目录中:
//写入到磁盘根目录
privatebooleanwriteResponseBodyToDisk(ResponseBodybody){
FilefutureStudioIconFile=newFile(Environment.getExternalStorageDirectory()+File.separator+"
atom.deb"
InputStreaminputStream=null;
OutputStreamoutputStream=null;
byte[]fileReader=newbyte[4096];
finallongfileSize=body.contentLength();
longfileSizeDownloaded=0;
inputStream=body.byteStream();
outputStream=newFileOutputStream(futureStudioIconFile);
while(true){
intread=inputStream.read(fileReader);
if(read==-1){
break;
outputStream.write(fileReader,0,read);
fileSizeDownloaded+=read;
filedownload:
"
+fileSizeDownloaded+"
of"
+fileSize);
finallongfinalFileSizeDownloaded=fileSizeDownloaded;
runOnUiThread(newRunnable(){
@Oride
publicvoidrun(){
+finalFileSizeDownloaded+"
outputStream.flush();
returntrue;
returnfalse;
}finally{
if(inputStream!
=null){
inputStream.close();
if(outputStream!
outputStream.close();
这样我们就可以非常高效的下载大文件了,最后友情提醒(如果是6.0以上另外再申请权限):
uses-permissionandroid:
name="
android.permission.INTERNET"
/>
android.permission.WRITE_EXTERNAL_STORAGE"
注解
尽管文章前面已经把Retrofit2注解基本了解完了,但是有必要多了解一些其他的注解,或许您正好有这样的场景需求,他们分别可作用于方法和参数:
@Headers:
用于在方法添加请求头:
@Streaming
如果您正在下载一个大文件,Retrofit2将尝试将整个文件移动到内存中。
为了避免这种,我们必须向请求声明中添加一个特殊的注解@Streaming
@Streaming
@GET
downloadFileByDynamicUrlAsync(@UrlStringfileUrl);
@Header:
用于在方法参数里动态添加请求头:
C