前言
本文是纯RetrofitDemo,和RxJava无关,如有错误请直接指出,感谢。
文档
GitHub:
https://github.com/square/retrofit
官方文档:
http://square.github.io/retrofit/
本文测试接口:
String URL = “https://api.douban.com/v2/movie/top250?start=0&count=10“; //豆瓣接口
引入
compile ‘com.squareup.retrofit2:retrofit:2.1.0’//retrofit依赖
compile ‘com.squareup.retrofit2:converter-scalars:2.1.0’//场景是这样,服务端返回一个不定类型的json数据,无法确定映射的Gson对象。
compile ‘com.squareup.retrofit2:converter-gson:2.1.0’//retrofit内部封装的GSON
compile ‘com.squareup.okhttp3:logging-interceptor:3.4.1’//log
注意加粗那个converter,converter有如下:
Gson: com.squareup.retrofit2:converter-gson
Jackson: com.squareup.retrofit2:converter-jackson
Moshi: com.squareup.retrofit2:converter-moshi
Protobuf: com.squareup.retrofit2:converter-protobuf
Wire: com.squareup.retrofit2:converter-wire
Simple XML: com.squareup.retrofit2:converter-simplexml
Retrofit基础:
初始化Retrofit
//日志拦截器
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
//打印retrofit日志
Log.i(TAG, "retrofitBack = " + message);
}
});
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
//超时时间 不设置的话 默认30秒
// .connectTimeout(mTimeOut, TimeUnit.SECONDS)
// .readTimeout(mTimeOut, TimeUnit.SECONDS)
// .writeTimeout(mTimeOut, TimeUnit.SECONDS)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)//增加返回值为String的支持
.client(client)//指定okHttpClient
.addConverterFactory(ScalarsConverterFactory.create())//返回对象支持
.addConverterFactory(GsonConverterFactory.create())//增加返回值为Gson的支持(返回实体类)
.build();
初始化RequestApi,请求接口实例
//这里采用的是Java的动态代理模式,得到请求接口对象
final RequestApi PostApi = retrofit.create(RequestApi.class);
RequestApi.class
package zj.playretrofit;
import io.reactivex.Flowable;
import io.reactivex.Observable;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;
import retrofit2.http.Query;
public interface RequestApi {
String URL = "https://api.douban.com/v2/movie/top250?start=0&count=10"; //豆瓣接口
/**
* 结合rxJava
*/
@GET("{url}")
Observable<ResponseData> getPathDoubadataRx(@Path("url") String url);
@GET("v2/movie/top250")
Observable<ResponseData> getDoubadata(@Query("start") String start, @Query("count") String count);
@FormUrlEncoded
@POST("v2/movie/top250")
Flowable<ResponseData> postDoubanData(@Field("start") String start, @Field("count") String count);
}
执行请求接口
这里的ResponseBean是我根据豆瓣返回的字段用Bean生成工具生成的一个实体对象。
这里的Call/CallBack对象,看包名,是retrofit的。
import retrofit2.Call;
import retrofit2.Callback;
简单看下源码:
Call
这个类是个interface,它的实现类是OkHttpCall,就是说这个对象是就是Retrofit封装OkHttp的关键对象,它就类似一个OkHttp的代理人,如下代码所示进行enqueue操作。Callback
这个就纯粹是一个回调用的接口实例了,没太大意义。
/**
* 执行并显示“请求接口”
*
* @param call
*/
private void doCall(Call<ResponseBean> call) {
//call#enqueue请求网络
if (!call.isExecuted()) {
call.enqueue(new Callback<ResponseBean>() {
@Override
public void onResponse(Call<ResponseBean> call, Response<ResponseBean> response) {
Log.d(TAG, response.body() == null ? "null" : response.body().toString());
PublicUtils.isMainThread();
}
@Override
public void onFailure(Call<ResponseBean> call, Throwable t) {
Log.d(TAG, "失败" + t.toString());
PublicUtils.isMainThread();
}
});
}
}
Retrofit请求字段:
用于Http Get请求传递参数.如:
@Query、@QueryMap
@GET("group/users")
Call<List<User>> groupList(@Query("id") int groupId);
等同于:
@GET("group/users?id=groupId")
即将@Query的key-value添加到url后面组成get方式的参数,@QueryMap同理
@Field
用于Post方式传递参数,需要在请求接口方法上添加@FormUrlEncoded,即以表单的方式传递参数.示例:
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
@Path
用于URL上占位符.如:
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
将groupId变量的值替换到url上的id位置。
@Part
配合@Multipart使用,一般用于文件上传,看官方文档示例:
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
@Header
添加http header
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)
等同于
@Headers("Authorization: authorization")//这里authorization就是上面方法里传进来变量的值
@GET("widget/list")
Call<User> getUser()
@Headers
跟@Header作用一样,只是使用方式不一样,@Header是作为请求方法的参数传入,@Headers是以固定方式直接添加到请求方法上.示例:
@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call<List<Widget>> widgetList();
多个设置:
@Headers({
"Accept: application/vnd.github.v3.full+json",
"User-Agent: Retrofit-Sample-App"
})
@GET("widget/list")
Call<List<Widget>> widgetList();
验证以及log观察
运行本文的demo进行测试。本文主要进行了3种类型的请求测试。
1.Post请求:
findViewById(R.id.btn_request_post).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "请求发起...post");
doCall(PostApi.postDoubanData("0", "10"));//传入district的值,得到Call对象
}
});
@FormUrlEncoded
@POST("v2/movie/top250")
Call<ResponseBean> postDoubanData(@Field("start") String start, @Field("count") String count);
Log观察:
11-30 16:43:56.716 30840-30840/zj.playretrofit D/PlayReTro: 请求发起...post
11-30 16:43:56.719 30840-5491/zj.playretrofit I/PlayReTro: retrofitBack = --> POST https://api.douban.com/v2/movie/top250 http/1.1
......
11-30 16:43:56.720 30840-5491/zj.playretrofit I/PlayReTro: retrofitBack = start=0&count=10
11-30 16:43:56.720 30840-5491/zj.playretrofit I/PlayReTro: retrofitBack = --> END POST (16-byte body)
11-30 16:43:57.856 30840-5491/zj.playretrofit I/PlayReTro: retrofitBack = <-- 200 OK https://api.douban.com/v2/movie/top250 (1134ms)
......
11-30 16:43:57.868 30840-5491/zj.playretrofit I/PlayReTro: retrofitBack = {"count": 10, "start": 0, "total": 250, "subjec...}
2.Get请求:
findViewById(R.id.btn_request_get).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "请求发起...get & query");
doCall(PostApi.getDoubadata("0", "10"));
}
});
@GET("v2/movie/top250")
Call<ResponseBean> getDoubadata(@Query("start") String start, @Query("count") String count);
Log观察:
11-30 17:21:36.430 8857-8931/zj.playretrofit I/PlayReTro: retrofitBack = --> GET https://api.douban.com/v2/movie/top250?start=0&count=10 http/1.1
11-30 17:21:36.430 8857-8931/zj.playretrofit I/PlayReTro: retrofitBack = --> END GET
11-30 17:21:37.398 8857-8931/zj.playretrofit I/PlayReTro: retrofitBack = <-- 200 OK https://api.douban.com/v2/movie/top250?start=0&count=10 (967ms)
......
11-30 17:21:37.411 8857-8931/zj.playretrofit I/PlayReTro: retrofitBack = {"count": 10, "sta...}
3.GET以地址的方式请求:
findViewById(R.id.btn_request_single_path).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "请求发起...path");
String url = "v2/book/1003078";
doCall(PostApi.getPathDoubadata(url));
}
});
@GET("{url}")
Call<ResponseBean> getPathDoubadata(@Path("url") String url);
Log观察
11-30 17:27:39.305 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = --> GET https://api.douban.com/v2%2Fbook%2F1003078 http/1.1
11-30 17:27:39.305 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = --> END GET
11-30 17:27:39.454 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = <-- 200 OK https://api.douban.com/v2%2Fbook%2F1003078 (148ms)
11-30 17:27:39.454 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = Date: Thu, 30 Nov 2017 09:27:37 GMT
11-30 17:27:39.454 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = Content-Type: application/json; charset=utf-8
11-30 17:27:39.454 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = Transfer-Encoding: chunked
11-30 17:27:39.454 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = Connection: keep-alive
11-30 17:27:39.454 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = Keep-Alive: timeout=30
11-30 17:27:39.454 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = Vary: Accept-Encoding
11-30 17:27:39.454 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = X-Ratelimit-Remaining2: 99
11-30 17:27:39.455 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = X-Ratelimit-Limit2: 100
11-30 17:27:39.455 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = Expires: Sun, 1 Jan 2006 01:00:00 GMT
11-30 17:27:39.455 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = Pragma: no-cache
11-30 17:27:39.455 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = Cache-Control: must-revalidate, no-cache, private
11-30 17:27:39.455 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = Set-Cookie: bid=IMz-P3yeOSw; Expires=Fri, 30-Nov-18 09:27:37 GMT; Domain=.douban.com; Path=/
11-30 17:27:39.455 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = X-DOUBAN-NEWBID: IMz-P3yeOSw
11-30 17:27:39.455 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = X-DAE-Node: daisy3d
11-30 17:27:39.455 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = X-DAE-App: book
11-30 17:27:39.455 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = Server: dae
11-30 17:27:39.457 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack =
11-30 17:27:39.457 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = {"rating":{"max":10,"numRaters":11413,"average":"9.2","min":0},"subtiitle":"","author_intro":"圣埃克苏佩里(1900-1944)1900年,尼采逝世。这一年,安德烈・纪德在布鲁塞尔一次会议上宣...}
11-30 17:27:39.457 8857-14147/zj.playretrofit I/PlayReTro: retrofitBack = <-- END HTTP (6406-byte body)
11-30 17:27:39.461 8857-8857/zj.playretrofit D/PlayReTro: ResponseBean{count=0, start=0, total=0, title='小王子', subjects=null}
Demo下载,博客推荐
Demo下载:
http://download.csdn.net/download/user11223344abc/10139703
博客推荐:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0915/3460.html