Type-safe HTTP client for Android and Java by Square, Inc.
官网:http://square.github.io/retrofit/
API:http://square.github.io/retrofit/2.x/retrofit/
参考:http://gank.io/post/56e80c2c677659311bed9841
http://blog.csdn.net/lmj623565791/article/details/51304204
主要记录一下GET,POST请求,以及Query,Path等注解的理解以及使用。主要有:
GET方式请求String
GET方式请求Json
GET方式访问自签名网站https
POST方式请求Json(需要header情况)
Converter:用于对象转化的。默认情况下,Retrofit 请求结果为responsebody型
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
T toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
其中 T body = serviceMethod.toResponse(catchingBody);就是将ResponseBody通过Converter转换成相应的类型
Retrofit定义好的转化器有下面几种:
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
Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars
其中Gson,Jackson,Moshi是用来转换Json对象的
Scalars 转换基本类型和String,eg:int,boolen,byte…
Simple XML:xml
Protobuf和Wire我还没有用过。
需要自定义的看这里:http://blog.csdn.net/lmj623565791/article/details/51304204
GET方式请求String
创建一个接口RequsetService
/** * Created by Administrator on 2016/5/4. */
public interface RequsetService {
/** * https://api.douban.com/v2/movie/top250?start=0&count=10 * GET方式请求String */
@GET("top250")
Call<String> getTopMovieStr(@Query("start") int start, @Query("count") int count);
}
这里我response的类型是一个String,所以Call里面泛型为String
通过Retrofit完成上述请求
/**
* method: GET
*
* @Query response:String
*/
private void getStrByGetMethod() {
String baseUrl = "https://api.douban.com/v2/movie/";
Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl).addConverterFactory(ScalarsConverterFactory.create()).build();
RequsetService requsetService = retrofit.create(RequsetService.class);
Call<String> call = requsetService.getTopMovieStr(0, 10);
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
Log.e(TAG, "call:" + call.toString());
Log.e(TAG, "response:" + response.body());
}
@Override
public void onFailure(Call<String> call, Throwable t) {
}
});
}
GET方式请求Json
创建一个接口
@GET("top250")
Call<MovieEntity> getTopMovieJson(@Query("start") int start, @Query("count") int count);
Retrofit完成请求
/** * method: GET * * @Query response:Gson */
private void getJsonByGetMethod() {
String baseUrl = "https://api.douban.com/v2/movie/";
Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl).addConverterFactory(GsonConverterFactory.create()).build();
RequsetService requsetService = retrofit.create(RequsetService.class);
Call<MovieEntity> call = requsetService.getTopMovieJson(0, 10);
Log.e(TAG, "request:" + call.request().toString());
call.enqueue(new Callback<MovieEntity>() {
@Override
public void onResponse(Call<MovieEntity> call, Response<MovieEntity> response) {
tvRequset.setText(response.body().toString());
Log.e(TAG, "response:" + response.body().toString());
}
@Override
public void onFailure(Call<MovieEntity> call, Throwable t) {
}
});
}
GET方式访问自签名网站https
创建接口
@GET
Call<String> getHttpsHtml(@Url String url);
Retrofit完成请求
/** * method: GET * @Url * response:String */
private void getHttpsHtml(){
InputStream[] inputStream = new InputStream[]{new Buffer().writeUtf8(CER_WIFI).inputStream()};
SSLSocketFactory sslSocketFactory = HttpsUtils.getSslSocketFactory(inputStream, null, null);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.sslSocketFactory(sslSocketFactory);
OkHttpClient client = httpClient.build();
String baseUrl = "https://www.wifi4.cn/wifi/yyhuang/";
Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl).addConverterFactory(ScalarsConverterFactory.create()).client(client).build();
RequsetService requsetService = retrofit.create(RequsetService.class);
Call<String> call = requsetService.getHttpsHtml("BC96802F9960");
Log.e(TAG, "request:" + call.request().toString());
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
Log.e(TAG, "call:" + call.toString());
Log.e(TAG, "response:" + response.body());
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG, "onFailure call:" + call.toString());
Log.e(TAG, "onFailure response:" + t.toString());
}
});
}
POST方式请求Json(需要header情况)
创建一个接口
@POST("login")
Call<Object> getInfoByPost(@Body String str);
我这里Body写成String,是因为我的数据需要加密,如果不需要加载,可以直接传对象
Retrofit完成请求
/** * POST * @Body */
private void loginByPostMethod() {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("ver", "V3.0.6")
.header("ctype", "0")
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
});
OkHttpClient client = httpClient.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://xxxx:11203/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
RequsetService requsetService = retrofit.create(RequsetService.class);
String body = "xxx";
Call<Object> call = requsetService.getInfoByPost(body);
Log.e(TAG, "url:" + call.request().url());
call.enqueue(new Callback<Object>() {
@Override
public void onResponse(Call<Object> call, Response<Object> response) {
// tvRequset.setText(response.body().toString());
Log.e(TAG, "response:" + response.body());
}
@Override
public void onFailure(Call<Object> call, Throwable t) {
}
});
}
@Query (询问):Query 作为符号“?”,然后再将Query 的参数拼接到Url,value转换成String,null忽略。以@GET(“/list”)为例:
简单例子:
Call<ResponseBody> getListMethod(@Query(“page”) int page)
foo.getListMethod(1) :baseUrl /list?page=1.
Array/Varargs例子:
Call<ResponseBody> getListMethod(@Query(“category”) String… categories)
foo.getListMethod(“bar”, “baz”) :baseUrl /list?category=bar&category=baz.
encoded = true例子:
Call<ResponseBody> getListMethod(@Query(value=”foo”, encoded=true) String foo)
foo.getListMethod(“foo+bar”) :baseUrl /list?foo=foo+bar.
@Path(路径):请求的URL可以根据使用的方法替换块和参数进行动态更新。替换块是由{ 和 } 环绕的字母数字字符串构成,而相应的参数必须用 @Path 注解标注,同时要求注解的参数使用相同的字符串,以@GET(“/user/{name}”)为例:
简单例子:
Call<ResponseBody> exampleMethod(@Path(“name”) String name)
foo.exampleMethod(“John”) :baseUrl /user/John.
encoded 例子:
Call<ResponseBody> encodedMethod(@Path(“name”) String name)
foo.encodedMethod(“John+Doe”) :baseUrl /user/John%2BDoe .
encoded = true例子:
Call<ResponseBody> encodedMethod(@Path(value=”name”, encoded=true) String name)
foo.encodedMethod(“John+Doe”) :baseUrl /user/John%+Doe .
@QueryMap: @GET(“/search”)
Call<ResponseBody> exampleMethod(@QueryMap Map<String, String> filters);
foo.exampleMethod(ImmutableMap.of(“foo”, “bar”, “kit”, “kat”)), baseUrl/search?foo=bar&kit=kat.
Call<ResponseBody> exampleMethod(@QueryMap(encoded=true) Map<String, String> filters);
foo.exampleMethod(ImmutableMap.of(“foo”, “foo+bar”)), baseUrl/search?foo=foo+bar.
@Body: 声明一个对象当作 HTTP 请求体, @POST/PUT (“users/new”),用于POST/PUT请求
@POST("users/new")
Call<User> createUser(@Body User user);
@FormUrlEncoded: application/x-www-form-urlencoded方式提交form-encoded 数据(表单数据),请求类似于下面这样:
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
首先,Content-Type 被指定为 application/x-www-form-urlencoded;其次,提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。了解其他提交方式:未完。
@Field: 一般用于表单的方式传递键值对,多用于POST
简单例子:
@FormUrlEncoded @POST("/") Call<ResponseBody> example(@Field("name") String name,@Field("occupation") String occupation);
用法:foo.exampleMethod(“Bob Smith”, “President”),body:name=Bob+Smith&occupation=President.
Array/Varargs例子:
@FormUrlEncoded @POST(“/list”) Call<ResponseBody> exampleMethod(@Field(“name”) String… names);
用法:foo.exampleMethod(“Bob Smith”, “Jane Doe”),body:name=Bob+Smith&name=Jane+Doe.
@FieldMap:
简单例子:
@FormUrlEncoded @POST("/things") Call<ResponseBody> things(@FieldMap Map<String, String> fields); ;
用法:foo.things(ImmutableMap.of(“foo”, “bar”, “kit”, “kat”), request body :foo=bar&kit=kat.
@Headers: 设置静态的 header,header 不能互相覆盖。
@Headers("Cache-Control: max-age=640000")
@GET("/")
@Headers({
"X-Foo: Bar",
"X-Ping: Pong"
})
@GET("/")
@Header: 更新一个请求的 header,必须给 @Header 提供相应的参数,如果参数的值为空 header 将会被忽略.
@GET("/") Call<ResponseBody> foo(@Header("Accept-Language") String lang);
@Multipart: multipart/form-data方式提交multipart数据,请求类似于下面这样:,(上传文件)
POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png
PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
@Part: 一般用于上传文件
@Multipart @POST("/") Call<ResponseBody> example(@Part MultipartBody.Part photo,@Part("description") String description,@Part(value = "image", encoding = "8-bit") RequestBody image);
eg:
File file = new File(Environment.getExternalStorageDirectory(), "icon.png");
RequestBody photoRequestBody = RequestBody.create(MediaType.parse("image/png"), file);
MultipartBody.Part photo = MultipartBody.Part.createFormData("photos", "icon.png", photoRequestBody);
Call<ResponseBody> call = example(photo, RequestBody.create(null, "abc"), photoRequestBody );
@PartMap: 一般用于多文件上传
@Multipart @POST("/upload") Call<ResponseBody> upload(@Part("file") RequestBody file,@PartMap Map<String, RequestBody> params);
File file = new File(Environment.getExternalStorageDirectory(), "messenger_01.png");
RequestBody photo = RequestBody.create(MediaType.parse("image/png", file);
Map<String,RequestBody> photos = new HashMap<>();
photos.put("photos\"; filename=\"icon.png", photo);
photos.put("username", RequestBody.create(null, "abc"));
Call<ResponseBody> call = upload(null,photos);
代码以后再上传
第一次使用Retrofit,如果有什么问题或者BUG,希望能给我留言