其他文章:https://blog.csdn.net/chenjie0932/article/details/79558050
https://blog.csdn.net/u011371324/article/details/80568891
https://blog.csdn.net/q469587851/article/details/79621447
新加:
https://www.jianshu.com/p/c0bb7b098a58
先添加库,记得在清单加上网络权限
// Okhttp库
compile 'com.squareup.okhttp3:okhttp:3.1.2'
// Retrofit库
compile 'com.squareup.retrofit2:retrofit:2.0.2'
//关于数据解析器(Converter)
compile 'com.squareup.retrofit2:converter-scalars:2.0.0'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
//打印日志
compile 'com.squareup.okhttp3:logging-interceptor:3.1.2'
retrofit介绍,各种注解
package com.example.administrator.myretrofit.demo;
import java.util.Map;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.HTTP;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
import retrofit2.http.PartMap;
import retrofit2.http.Path;
import retrofit2.http.Query;
import retrofit2.http.QueryMap;
import retrofit2.http.Streaming;
import retrofit2.http.Url;
/**
* Created by Administrator on 2018/9/27.
*/
/*
Retrofit注解
Retrofit注解分为三大类,分别是HTTP请求方法注解(8种)、标记类注解(3种)和参数类注解(11种)。
• HTTP请求方法注解:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、HTTP
• 标记类注解:FormUrlEncoded、Multipart、Streaming
• 参数类注解:Headers、Header、Body、Field、FieldMap、Part、PartMap、Path、Query、QueryMap、Url
作者:低调的大雄
链接:https://www.jianshu.com/p/4d67fe493ebf
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
注1: Retrofit2 的baseUlr 必须以 /(斜线) 结束,不然会抛出一个IllegalArgumentException,所以如果你看到别的教程没有以 / 结束,那么多半是直接从Retrofit 1.X 照搬过来的。
*/
public interface GetRequest_Demo {
//第一类:网络请求方法
/*
a. @GET、@POST、@PUT、@DELETE、@HEAD
以上方法分别对应 HTTP中的网络请求方式
*/
@GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
Call<ResponseBody> getCall();
/*
b. @HTTP
作用:替换@GET、@POST、@PUT、@DELETE、@HEAD注解的作用 及 更多功能拓展
具体使用:通过属性method、path、hasBody进行设置
*/
/**
* method:网络请求的方法(区分大小写) * path:网络请求地址路径 * hasBody:是否有请求体
*/
@HTTP(method = "GET", path = "blog/{id}", hasBody = false)
Call<ResponseBody> getCall(@Path("id") int id); // {id} 表示是一个变量 // method 的值 retrofit 不会做处理,所以要自行保证准确
// 第二类:标记
/*a. @FormUrlEncoded作用:表示发送form-encoded的数据每个键值对需要用@Filed来注解键名,随后的对象需要提供值。
b. @Multipart作用:表示发送form-encoded的数据(适用于 有文件 上传的场景)每个键值对需要用@Part来注解键名,随后的对象需要提供值。
---------------------
本文来自 q469587851 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/q469587851/article/details/79621447?utm_source=copy */
/**
* 表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
* * <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值
*/
@POST("/form")
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded1(
@Field("username") String name, @Field("age") int age);
/**
* {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型
* * 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),
*/
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload1(
@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);
//第三类:网络请求参数
/*a. @Header & @Headers
作用:添加请求头 &添加不固定的请求头
具体使用如下:*/
// @Header
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization, @Header("token") String token);
// @Headers
@Headers("Authorization: authorization")
@GET("user")
Call<User> getUser();
//添加多个固定请求头
@Headers({
"key1:value1", "key2:value2"
})
@GET("user")
Call<User> getUser2();
// @GET
// Call<User> weather(@HeaderMap Map<String, String> headers, @Url String url, @Query("cityname") String cityName);
// 以上的效果是一致的。
// 区别在于使用场景和使用方式
// 1. 使用场景:@Header用于添加不固定的请求头,@Headers用于添加固定的请求头
// 2. 使用方式:@Header作用于方法的参数;@Headers作用于方法
/*b. @Body
作用:以 Post方式 传递 自定义数据类型 给服务器
特别注意:如果提交的是一个Map,那么作用相当于 @Field
不过Map要经过 FormBody.Builder 类处理成为符合 Okhttp 格式的表单,如:*/
// FormBody.Builder builder = new FormBody.Builder();
// builder.add("key","value");
/*c. @Field & @FieldMap
作用:发送 Post请求 时提交请求的表单字段
具体使用:与 @FormUrlEncoded 注解配合使用*/
/**
* 表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
* <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值
*/
@POST("/form")
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded2(
@Field("username") String name, @Field("age") int age);
/**
* Map的key作为表单的键
*/
@POST("/form")
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded2(
@FieldMap Map<String, Object> map);
/*d. @Part & @PartMap
作用:发送 Post请求 时提交请求的表单字段
与@Field的区别:功能相同,但携带的参数类型更加丰富,包括数据流,所以适用于 有文件上传 的场景*/
/**
* {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型
* 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),
*/
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload2(
@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);
/**
* PartMap 注解支持一个Map作为参数,支持 {@link RequestBody } 类型,
* 如果有其它的类型,会被{@link retrofit2.Converter}转换,如后面会介绍的 使用{@link com.google.gson.Gson} 的
* {@link retrofit2.converter.gson.GsonRequestBodyConverter}
* 所以{@link MultipartBody.Part} 就不适用了,所以文件只能用<b> @Part MultipartBody.Part </b>
*/
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload2(@PartMap Map<String, RequestBody> args, @Part MultipartBody.Part file);
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload13(@PartMap Map<String, RequestBody> args);
/*e. @Query和@QueryMap
作用:用于 @GET 方法的查询参数(Query = Url 中 ‘?’ 后面的 key-value)
如:url = http://www.println.net/?cate=android,其中,Query = cate*/
@GET("/")
Call<String> cate(@Query("cate") String cate);
//http://japi.juhe.cn/qqevaluate/qq?key=96efc220a4196fafdfade0c9d1e897ac&qq=295424589
@GET("/qqevaluate/qq")
Call<String> getQQData(@Query("key") String appkey, @Query("qq") String qq);
//在注解中指定路径,定义相对应的参数的集合
@GET("qqevaluate/qq")
Call<String> getQQDataMap(@QueryMap Map<String, String> map);
// 其使用方式同 @Field与@FieldMap,这里不作过多描述
/*f. @Path
作用:URL地址的缺省值
具体使用:*/
@GET("users/{user}/repos")
Call<ResponseBody> getBlog(@Path("user") String user);
// 访问的API是:https://api.github.com/users/{user}/repos
// 在发起请求时, {user} 会被替换为方法的第一个参数 user(被@Path注解作用)
/*g. @Url
作用:直接传入一个请求的 URL变量 用于URL设置
具体使用:*/
@GET
Call<ResponseBody> testUrlAndQuery(@Url String url, @Query("showAll") boolean showAll);
// 当有URL注解时,@GET传入的URL就可以省略
// 当GET、POST...HTTP等方法中没有设置Url时,则必须使用 {@link Url}提供
//PDF文件Retrofit下载@Streaming 是注解大文件的,小文件可以忽略不加注释,但是大文件一定需要注释,不然会出现OOM。
@Streaming
@GET
Call<ResponseBody> retrofitDownloadFile(@Url String fileUrl);
/*@FormUrlEncoded注解表示from表单*/
/*通过query的方式,其实是把参数拼在URl的后面,使用body是放在请求体*/
@POST("/form")
Call<ResponseBody> testFileUpload2(
@Query("name") String name, @Query("age") String age);
@POST("/form")
Call<ResponseBody> testFileUpload2(
@QueryMap Map<String, String> map);
//放在请求体 https://blog.csdn.net/wzl_show/article/details/76169501
@POST("/form")
Call<ResponseBody> testFileUpload3(
@Body Map<String, String> map );
@POST("/form")
Call<ResponseBody> testFileUpload3(
@Body User user );
@POST("/form")
Call<ResponseBody> testFileUpload3(
@Body String user );
}
在MainActivity进行创建
//创建Retrofit对象
retrofit = new Retrofit.Builder()
.baseUrl("http://www.baidu.com/")
.addConverterFactory(ScalarsConverterFactory.create()) //设置内容格式,这种对应的数据返回值是String类型
.build();
}
private void bb () {
// 具体使用
GetRequest_Demo service = retrofit.create(GetRequest_Demo.class);
// @FormUrlEncoded
Call<ResponseBody> call1 = service.testFormUrlEncoded1("Carson", 24);
// @Multipart
MediaType textType = MediaType.parse("text/plain");
RequestBody name = RequestBody.create(textType, "Carson");
RequestBody age = RequestBody.create(textType, "24");
RequestBody file = RequestBody.create(MediaType.parse("application/octet-stream"), "这里是模拟文件的内容");
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", "test.txt", file);
Call<ResponseBody> call3 = service.testFileUpload1(name, age, filePart);
// @Field
Call<ResponseBody> call2 = service.testFormUrlEncoded2("Carson", 24);
// @FieldMap
// 实现的效果与上面相同,但要传入Map
Map<String, Object> map = new HashMap<>();
map.put("username", "Carson");
map.put("age", 24);
Call<ResponseBody> call0 = service.testFormUrlEncoded2(map);
// @Part
Call<ResponseBody> call4 = service.testFileUpload2(name, age, filePart);
// ResponseBodyPrinter.printResponseBody(call4);
// @PartMap
// 实现和上面同样的效果
Map<String, RequestBody> fileUpload2Args = new HashMap<>();
fileUpload2Args.put("name", name);
fileUpload2Args.put("age", age);
//这里并不会被当成文件,因为没有文件名(包含在Content-Disposition请求头中),但上面的 filePart 有
//fileUpload2Args.put("file", file);
Call<ResponseBody> call5 = service.testFileUpload2(fileUpload2Args, filePart); //单独处理文件
// ResponseBodyPrinter.printResponseBody(call5);
}
还可以增加拦截器,设置请求头,打印日志等
//日志
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//统一在url后面添加参数
AppendUrlParamInterceptor appendUrlParamInterceptor = new AppendUrlParamInterceptor();
//统一增加请求头
AppendHeaderParamInterceptor header = new AppendHeaderParamInterceptor();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor)
.addInterceptor(appendUrlParamInterceptor)
.addInterceptor(header)
.build();
//步骤4:创建Retrofit对象
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://fy.iciba.com/") // 设置 网络请求 Url
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create()) //设置使用Gson解析(记得加入依赖)
.build();
AppendHeaderParamInterceptor.java
public class AppendHeaderParamInterceptor implements Interceptor {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();//拿到发送的请求
Headers headers = request.headers().newBuilder().add("token","mytoken").build();
Request newRequest = request.newBuilder().headers(headers).build();
return chain.proceed(newRequest);
}
}
AppendUrlParamInterceptor.java
/**
* Created by Administrator on 2018/9/27.
*
* 拦截器,拿到请求,并在请求uil上增加参数
*/
public class AppendUrlParamInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();//拿到发送的请求
HttpUrl httpUrl = request.url().newBuilder().addQueryParameter("version","1.0")
.addQueryParameter("channel","360")
.addQueryParameter("versionCode","10")
.addQueryParameter("deviceId","abasersgdhdjjfs5688")
.build();
//重要一步 使用新的url构建一个Request发送给后台
Request newRequest = request.newBuilder().url(httpUrl).build();
return chain.proceed(newRequest);
}
}
// 本文来自 zhoushenxian 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/coderinchina/article/details/78669503?utm_source=copy
HandleNoNetInterceptor.java 判断网络
public class HandleNoNetInterceptor implements Interceptor {
private Context content;
public HandleNoNetInterceptor(Context content) {
this.content = content;
}
@Override
public Response intercept(Chain chain) throws IOException {
// if(NetUtils.isNetworkAvalible(content)){
// return chain.proceed(chain.request());
// }else{
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(content,"网络异常,请检查你的网络",Toast.LENGTH_LONG).show();
}
});
throw new RuntimeException("网络异常了~~~~~");
// }
}
}
a. 关于数据解析器(Converter)Retrofit支持多种数据解析方式使用时需要在Gradle添加依赖数据解析器Gradle依赖
Gsoncom.squareup.retrofit2:converter-gson:2.0.2
Jacksoncom.squareup.retrofit2:converter-jackson:2.0.2
Simple XMLcom.squareup.retrofit2:converter-simplexml:2.0.2
Protobufcom.squareup.retrofit2:converter-protobuf:2.0.2
Moshicom.squareup.retrofit2:converter-moshi:2.0.2
Wirecom.squareup.retrofit2:converter-wire:2.0.2
Scalarscom.squareup.retrofit2:converter-scalars:2.0.2