您的位置:首页 > 编程语言 > Java开发

Retrofit使用总结

2018-01-04 13:48 176 查看

相关内容介绍:

概述

如何使用

同步请求

异步请求

如何取消

各种路径 @Path @Query 等的如何 以及详细使用 Url 是什么样子

如何添加Converter modules 类型转换器 可以转换哪些类型

其他内容

自定义Gson对象

新的URL定义方式

Use an Interceptor from OkHttp(okhttp 使用拦截器)

RxJava Integration with CallAdapter(使用rxjava)

概述

Retrofit是由Square公司出品的针对于Android和Java的类型安全的Http客户端

Retrofit 实际上就是对okHttp的封装

较1.9 旧版本区别

新的Service定义方式,不再有同步和异步之分

Retrofit 2.0 上,只能定义一个模式,因此要简单得多。

import retrofit.Call;
public interface APIService {
/* Retrofit 2.0 */
@POST("/list")
Call<Repo> loadRepo();
}


调用同步请求,只需调用execute,而发起一个异步请求则是调用enqueue.

Call<Repo> call = service.loadRepo();
Repo repo = call.execute();


以上的代码会阻塞线程,因此你不能在安卓的主线程中调用,不然会报错 NetworkOnMainThreadException. 如果你要调用execute 方法,请在后台线程执行。

Call<Repo> call = service.loadRepo();
call.enqueue(new Callback<Repo>(){
@Override
publicvoid onResponse(Response<Repo> response){
}

@Override
publicvoid onFailure(Throwable t){
}
});


2.

取消正在进行中的业务

service 的模式变成Call的形式的原因是为了让正在进行的事务可以被取消。要做到这点,你只需调用

call.cancel()。


事务将会在之后立即被取消。

请求时 ,如果你的在baseUrl 后面没有后续的 Path 只是一个类似百度(http://www.baidu.com) 这样的一个请求,@GET 会报错 missing @GET 或者 @URL 我们可以是用这样的方式来解决(亲测可行)。

@GET("/")
Call<ResponseBody> getBaiduInfo();


retrofit 注解

方法注解,包含@GET、@POST、@PUT、@DELETE、@PATH、@HEAD、@OPTIONS、@HTTP。

标记注解,包含@FormUrlEncoded、@Multipart、@Streaming。

参数注解,包含@Query,@QueryMap、@Body、@Field,@FieldMap、@Part,@PartMap。

其他注解,@Path、@Header,@Headers、@Url

@HTTP:可以替代其他方法的任意一种(baseUrl :http://gank.io/api/

@HTTP(method = "GET", path = "data/{type}/{num}/{page}", hasBody = false)
Call<GankTypeEntity> getGankDataByHttp(@Path("type") String type, @Path("num") int num, @Path("page") int page);


@GET 请求(baseUrl :http://gank.io/api/

@GET("data/{type}/{num}/{page}")
Call<GankTypeEntity> getGankDataByGet(@Path("type") String type, @Path("num") int num, @Path("page") int page);


@Url : 传入一个完整的url(如:http:\www.baidu.com/) 。 会覆盖baseUrl 。适用于baseUrl不统一的情景下。

@GET
Call<ResponseBody> getBaiduInfo(@Url String url);


@Streaming:用于下载大文件(亲测可行,app内的apk下载地址,未能提供链接)

@Streaming
@GET
Call<ResponseBody> downloadFile(@Url String url);


@Query,@QueryMap:查询参数,用于GET查询,需要注意的是@QueryMap可以约定是否需要encode

@GET("users")
Call<List<GithubUser>> getUserByGroup(@Query("groupId")int groupId);

Call<List<News>> getNews((@QueryMap(encoded=true) Map<String, String> options); (未验证)


@Body:用于POST请求体,将实例对象根据转换方式转换为对应的json字符串参数,

这个转化方式是GsonConverterFactory定义的。

@POST("add")
Call<List<User>> addUser(@Body User user);


@Field,@FieldMap:Post方式传递简单的键值对,(baseUrl :http://gank.io/api/

需要添加@FormUrlEncoded表示表单提交 否则会报错

@Field parameters can only be used with form encoding. (parameter #1)Content-Type:application/x-www-form-urlencoded

@FormUrlEncoded
@POST("add2gank")
Call<ResponseBody>  postContent(@Field("url")String url,@Field("desc") String desc,@Field("who")String who,@Field("type")String type,@Field("debug")String debug);


@Part,@PartMap:用于POST文件上传

其中@Part MultipartBody.Part代表文件,@Part(“key”) RequestBody代表参数

需要添加@Multipart表示支持文件上传的表单,Content-Type: multipart/form-data

@Multipart
@POST("upload")
Call<ResponseBody> upload(@Part("description") RequestBody description,                              @Part MultipartBody.Part file)

// https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java // use the FileUtils to get the actual file by uri
File file = FileUtils.getFile(this, fileUri);    // create RequestBody instance from file
RequestBody requestFile =
RequestBody.create(MediaType.parse("multipart/form-data"), file);    // MultipartBody.Part is used to send also the actual file name
MultipartBody.Part body =
MultipartBody.Part.createFormData("picture", file.getName(), requestFile);        // add another part within the multipart request    String descriptionString = "hello, this is description speaking";    RequestBody description =            RequestBody.create(                    MediaType.parse("multipart/form-data"), descriptionString);


@Header:header处理,不能被互相覆盖,用于修饰参数,

//动态设置Header值
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)


也可以

//静态设置Header值
@Headers("Authorization: authorization")
//这里authorization就是上面方法里传进来变量的值
@GET("widget/list")Call<User> getUser()


@Headers 用于修饰方法,用于设置多个Header值:

@Headers({    "Accept: application/vnd.github.v3.full+json",    "User-Agent: Retrofit-Sample-App"})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);


Gson使用

需要导入以下依赖:

compile 'com.squareup.retrofit2:converter-gson:2.3.0'


以下为代码中使用方式:

mRetrofit = new Retrofit.Builder()
.baseUrl("http://www.baidu.com/")
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();


retrofit其他

Retrofit 支持的Converter modules 列表

Gson: com.squareup.retrofit:converter-gson

Jackson: com.squareup.retrofit:converter-jackson

Moshi: com.squareup.retrofit:converter-moshi

Protobuf: com.squareup.retrofit:converter-protobuf

Wire: com.squareup.retrofit:converter-wire

Simple XML: com.squareup.retrofit:converter-simplexml

url 问题

baseUrl 必须以“/” 结尾 否则会报错

在Retrofit2.0中,我们还可以在@Url里面定义完整的Url :

@GET("http://www.baidu.com/")
Call<ResponseBody> getBaiduInfo();


这样情况下,baseUrl 会被覆盖掉

拒绝encode

okHttp 默认会对Query 的参数进行编码 , 但是某些特殊的情况,我们并不希望如此。我们可以使用以下方式

@Query(value = "tag", encoded = false) String tag


OkHttp的支持

在Retrofit 2.0中,OkHttp 是必须的,并且自动设置为了依赖。下面的代码是从Retrofit 2.0的pom文件中抓取的。你不需要再做任何事情了。

<dependencies>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>okhttp</artifactId>
</dependency>  ...
</dependencies>


添加拦截器( 拦截器的具体使用后面的博客还会继续介绍 )

client = new OkHttpClient.Builder()
.retryOnConnectionFailure(true)
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Log.e("testBaidu","我这里是拦截器");
Response proceed = chain.proceed(chain.request());
return proceed;
}
})
.connectTimeout(15, TimeUnit.SECONDS)
.build();


Rxjava Retrofit使用

使用Rxjava 需要导入以下依赖:

compile 'com.squareup.re
ae27
trofit2:adapter-rxjava2:2.3.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'


下一步,在Retrofit Builder模式的列表中 调用addCallAdapterFactory:

mRetrofit = new Retrofit.Builder()
.baseUrl("http://www.baidu.com/")
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();


RxJava 相关代码(RxJava 此处指是提及,后续还会有博客进行详细介绍)

Observable<ResponseBody> baiduInfo =         manageService.getBaiduInfo();

baiduInfo
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ResponseBody>() {
@Override
public void onSubscribe(Disposable d) {

}

@Override
public void onNext(ResponseBody value) {
try {
Log.e("testBaidu", value.string());
} catch (IOException e) {
}
}

@Override
public void onError(Throwable e) {
Log.e("testBaidu","error ");
}

@Override
public void onComplete() {
Log.e("testBaidu", "onComplete");
}
});


注意如果需要访问网络
, 则 Schedulers.io 是必须的。否则就会报错。

相关参考资料

Retrofit2.0使用总结

Okhttp-wiki 之 Interceptors 拦截器
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息