关于Retrofit的讲解,我将写下面系列篇文章进行总结:html
- Get和Post请求的基本使用
- 上传图片
- 下载文件
- 添加拦截器
- ...(和RxJava联合使用、RxJava+Retrofit+OkHttp简单封装、统一错误处理)
讲解以前我必须先安利个网站模客,在学习Retrofit以前,各类网络请求若是想学习的话就必须有接口才能访问,Get请求还好说,但遇到Post请求,本身发送的是啥也不清楚,苦于本身不会后端写接口,因此以前对Retrofit的学习要么是各类找现成的API,要么就只是照猫画虎的敲了下并无实践,有了这个网站你就能够本身写接口本身访问来测测看Retrofit的运用到底对不对。java
具体该网站的使用见模客的使用这篇文章,下面咱们来学习Retrofit的使用吧android
//Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
//Gson converter
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
复制代码
第二个依赖主要是对Json数据进行解析的。git
和官网同样,能够看下官网介绍的代码,就是上面所写的步骤github
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
复制代码
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
复制代码
GitHubService service = retrofit.create(GitHubService.class);
复制代码
Call<List<Repo>> repos = service.listRepos("octocat");
复制代码
下面我将介绍个具体的例子,让没用过Retrofit的先熟悉下Retrofit如何使用json
public interface GetApi {
/** * 获取用户信息 * @return * @Query 注解 */
@GET("getUserInfo")
Call<UserInfo> getUserInfo(@Query("id") String userId);
}
复制代码
这个@Query注解是什么能够先不用管,下面会详细讲解。后端
UserInfo是咱们获得返回数据的数据Bean类api
private Retrofit retrofit;
retrofit = new Retrofit.Builder()
.baseUrl("http://mock-api.com/2vKVbXK8.mock/")
.addConverterFactory(GsonConverterFactory.create()) //返回的Json数据进行解析
.build();
复制代码
baseUrl:安全
这里的baseUrl是本身访问的Url的基类地址,加上刚才@GET("getUserInfo")中的getUserInfo
才是咱们真正要访问的地址,由于使用了@Query("id"),因此最终的访问地址为bash
http://mock-api.com/2vKVbXK8.mock/getUserInfo?id=userid
,此处的userid为本身传入的参数。
注意: baseUrl必需要以/
结尾!!!
addConverterFactory:
加这个addConverterFactory(GsonConverterFactory.create())
固定的,则会将返回的Json数据直接解析为咱们的数据Bean类
private GetApi getApi;
getApi = retrofit.create(GetApi.class);
复制代码
getApi.getUserInfo(userid).enqueue(new Callback<UserInfo>() {
@Override
public void onResponse(Call<UserInfo> call, Response<UserInfo> response) {
if (response != null && response.body() != null) {
//此处为获取到的信息
UserInfo userInfo = response.body();
}
}
@Override
public void onFailure(Call<UserInfo> call, Throwable t) {
Log.i(TAG, "onFailure: " + t);
}
});
复制代码
使用时别忘了申请网络权限哦,使用时可能会遇到如下问题:
CLEARTEXT communication to mock-api.com not permitted by network security policy
这是由于Android P
不容许明文访问,而前面的mock
地址是http
开头的,解决办法是在AndroidManifest
中的application
内加入下面这段代码便可:
android:usesCleartextTraffic="true"
复制代码
以上就是Retrofit最基本的一次网络请求,接下来咱们详细看下Retrofit网络请求接口中主要有哪些注解。
baseUrl为:http://mock-api.com/2vKVbXK8.mock/
访问地址
http://mock-api.com/2vKVbXK8.mock/api/getUserInfo?id=1234 //1234为传来的参数
复制代码
实例
@GET("api/getUserInfo")
Call<UserInfo> getUserInfo(@Query("id") String userId);
复制代码
public class UserInfo {
private String userId;
private String userName;
private String describe;
}
复制代码
当咱们要访问的地址为:baseUrl
+getUserInfo?id=1234
,以?
形式拼接一个参数这种格式时,就使用@Query
注解,该注解就是在getUserInfo后面添加?
,而且以id=传来的参数userId
的形式拼接url
访问地址
http://mock-api.com/2vKVbXK8.mock/api/getArticalInfo?id=405&page=1
复制代码
实例
@GET("api/getArticalInfo")
Call<ArticalInfo> getArticalInfo(@QueryMap Map<String, String> params);
复制代码
public class ArticalInfo {
private String articalName;
private String url;
}
复制代码
当要访问的地址是经过?
形式拼接多个参数时就使用@QueryMap
注解
具体使用:
Map<String, String> params = new HashMap<>();
params.put("id", "405");
params.put("page", "1");
getApi.getArticalInfo(params).enqueue(new Callback<ArticalInfo>() {
@Override
public void onResponse(Call<ArticalInfo> call, Response<ArticalInfo> response) {
if (response != null && response.body() != null) {
Log.i(TAG, "onRespons:" + response.body().toString());
}
}
@Override
public void onFailure(Call<ArticalInfo> call, Throwable t) {
Log.i(TAG, "onFailure: " + t);
}
});
复制代码
访问地址
http://mock-api.com/2vKVbXK8.mock/api/getDynamicInfo/1/data
http://mock-api.com/2vKVbXK8.mock/api/getDynamicInfo/2/data
复制代码
实例
@GET("api/getDynamicInfo/{param}/data")
Call<ResponseBody> getDynamicInfo(@Path("param")int param);
复制代码
当要访问的地址由某个参数动态拼接而成时,使用@Path
注解,上面实例中param这里具体填入的内容是后面调用该方法时传入的参数
getApi.getDynamicInfo(param).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
String str = new String(response.body().bytes());
Log.i(TAG, "onResponse: " + str);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.i(TAG, "onFailure: " + t);
}
});
复制代码
你们仔细看下,你会发现Call<ResponseBody>
这里和上面的不一样,这里填入的是ResponseBody
,当返回的具体数据不是咱们知道的Bean类时能够用这个,这样,咱们能够经过上述字符串的形式获取到返回的内容。
访问地址
http://mock-api.com/2vKVbXK8.mock/api/getDynamicUrlData
复制代码
实例
@GET
Call<ResponseBody> getDynamicUrl(@Url String url);
复制代码
当要访问的地址不仅是动态的变几个参数,而是整个地址都要变化,甚至是基类地址也要变化时,这种动态地址就要用到@Url注解
具体使用
String url = "http://mock-api.com/2vKVbXK8.mock/api/getDynamicUrlData"
getApi.getDynamicUrl(url).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
String str = new String(response.body().bytes());
Log.i(TAG, "onResponse: " + str);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.i(TAG, "onFailure: " + t);
}
});
复制代码
因此说这个注解很方便,上面全部注解所访问的连接都可经过此注解传入完整的Url进行访问。
注意
虽说最终访问的地址与原先的baseUrl无关,可是baseUrl仍是要以http://
或https://
开头,而且后面至少要跟一个字母或者其余东西,否则就会报错。
http://
复制代码
写成这个会报Invalid URL host: ""错误
http://a
复制代码
我实际测试时,这个a这里写什么均可以,没有以/
结尾也能够
静态添加头部信息:包含添加单个头部、添加多个头部
经过@Headers("")注解,内部以key:value的方式填写内容
访问地址
http://mock-api.com/2vKVbXK8.mock/api/staticHeaderInfo
复制代码
实例
静态添加单个头部
@Headers("version:1.1")
@GET("api/staticHeaderInfo")
Call<GetBean> getStaticHeadersInfo();
复制代码
静态添加多个头部
@Headers({"version:1.1",
"type:android"})
@GET("api/staticHeadersInfo")
Call<GetBean> getStaticMoreHeadersInfo();
复制代码
模客后台
动态添加单个头部信息
访问地址
http://mock-api.com/2vKVbXK8.mock/api/dynamicHeadersInfo
复制代码
实例
@GET("api/dynamicHeadersInfo")
Call<ResponseBody> getDynamicHeaderInfo(@Header("version") String version);
复制代码
getApi.getDynamicHeaderInfo("1.1.1").enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
复制代码
模客后台
能够看到咱们访问时确实在头部加入了version=1.1.1的信息。
动态添加多个头部信息
访问地址
http://mock-api.com/2vKVbXK8.mock/api/dynamicHeadersInfo
复制代码
实例
@GET("api/dynamicHeadersInfo")
Call<ResponseBody> getDynamicHeadersInfo(@HeaderMap Map<String, String> headers);
复制代码
Map<String, String> headers = new HashMap<>();
headers.put("version", "2.2.2");
headers.put("type", "Android");
getApi.getDynamicHeadersInfo(headers).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
}
复制代码
模客后台
能够看到咱们在访问的时候两个头部信息已经加载header中
对比着Get请求中的注解,Post请求中的注解就很好记了。
@Field 对应 @Query
@FieldMap 对应 @QueryMap
@Body 对应 @Url
注意
在Post请求中,尽可能不要使用@Query和@QueryMap,由于它传入的参数是直接拼接在url上的,不安全,而@Field和@FieldMap是写入到Body中的。
@FormUrlEncoded
用于修饰@Field
注解和@FieldMap
注解,将会自动将请求参数的类型调整为
application/x-www-form-urlencoded
访问地址
http://mock-api.com/2vKVbXK8.mock/api/fieldParam
复制代码
实例
@FormUrlEncoded
@POST("api/fieldParam")
Call<ResponseBody> postFieldFun(@Field("key") String key);
复制代码
记得加上@FormUrlEncoded
,不然会报如下错误:
@Field parameters can only be used with form encoding
复制代码
使用
private PostApi postApi;
postApi = retrofit.create(PostApi.class);
postApi.postFieldFun("myfittinglife").enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
String str = new String(response.body().bytes());
Log.i(TAG, "onResponse: " + str);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.i(TAG, "onFailure: " + t);
}
});
复制代码
模客后台
能够看到咱们经过@Field注解添加的参数是写在body中而不是直接拼接在Url后面
这里是根据咱们设立的规则来进行匹配的,固然咱们也能够选择文本或其余的方式进行匹配。
访问地址
http://mock-api.com/2vKVbXK8.mock/api/fieldMapParam
复制代码
实例
@FormUrlEncoded
@POST("api/fieldMapParam")
Call<ResponseBody> postFildMapFun(@FieldMap Map<String, String> params);
复制代码
@FieldMap时候于多个相同类型参数的传递
使用
Map<String, String> params = new HashMap<>();
params.put("key", "myfittinglife");
params.put("password", "123456");
postApi.postFildMapFun(params).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
String str = new String(response.body().bytes());
Log.i(TAG, "onResponse: " + str);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.i(TAG, "onFailure: " + t);
}
});
复制代码
模客后台
能够看到咱们传入body内的两个参数
3.3 能够看到@FieldMap
注解适合多个相同类型参数的传递,若是多个不一样类型传递的话,总不能写多个@Field
吧
Call<ResponseBody> postFieldFun(@Field("key") String key,@Field("num")int num);
若是要更多种类型的话那就更繁琐了,因此这里咱们能够用@Body
注解,直接传入一个对象过去,对象内可包含多种类型数据。
访问地址
http://mock-api.com/2vKVbXK8.mock/api/bodyParam
复制代码
实例
@POST("api/bodyParam")
Call<ResponseBody> postBodyFun(@Body PostBodyBean postBodyBean);
复制代码
public class PostBodyBean {
private String key;
private int num;
private boolean isTrue;
}
复制代码
使用
PostBodyBean postBodyBean = new PostBodyBean("myfittinglife",1,true);
postApi.postBodyFun(postBodyBean).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
String str = new String(response.body().bytes());
Log.i(TAG, "onResponse: " + str);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.i(TAG, "onFailure: " + t);
}
});
复制代码
模客后台
能够看到咱们传的Body
注意
使用@Body注解必定在建立Retrofit的时候加上.addConverterFactory(GsonConverterFactory.create())
,目的是将对象转化为json字符串进行传递,不然会报如下错误
Unable to create @Body converter for class PostBodyBean 复制代码
这两个注解和文件上传相关,在后面的文章中会进行详细讲解。
访问地址http开头,记得在AndroidManifest内的application中加入android:usesCleartextTraffic="true"
GET请求不能使用@Body注解
baseUrl网址末尾必定加/
斜杠
@Body注解必定要加.addConverterFactory(GsonConverterFactory.create())
当@GET或@POST注解的url为全路径时(可能和baseUrl不是一个域),会直接使用注解的url的 域。
使用@Path注解时,path对应的路径不能包含/
,不然会将其转化为%2F,报以下错误。在遇到想动态的拼接多节url时,仍是使用@Url吧。
Attempt to invoke virtual method 'byte[] okhttp3.ResponseBody.bytes()' on a null object reference
复制代码
以上就是关于Retrofit的一些注解的基本使用介绍,具体代码见Github.
为了简便观察,文章中只是使用了一个注解来创建接口,其实在实际使用时,能够多个注解连用,例以下面所示:
@GET("api/{param}/getUserInfo")
Call<UserInfo> getUserInfo(@Path("params") String param, @Query("id") String userId);
复制代码
具体怎么结合仍是要根据实际项目提供的url来使用。以上就是所有内容,能力有限,不对的地方还望指出,有帮助的话还望点个start,下篇文章见。