内容简介:讲解之前我必须先安利个网站模客,在学习Retrofit之前,各种网络请求如果想学习的话就必须有接口才能访问,Get请求还好说,但遇到Post请求,自己发送的是啥也不清楚,苦于自己不会后端写接口,所以之前对Retrofit的学习要么是各种找现成的API,要么就只是照猫画虎的敲了下并没有实践,有了这个网站你就可以自己写接口自己访问来测测看Retrofit的运用到底对不对。具体该网站的使用见模客的使用这篇文章,下面我们来学习Retrofit的使用吧第二个依赖主要是对Json数据进行解析的。
关于Retrofit的讲解,我将写下面系列篇文章进行总结:
- Get和Post请求的基本使用
- 上传图片
- 下载文件
- 添加拦截器
- ...(和RxJava联合使用、RxJava+Retrofit+OkHttp简单封装、统一错误处理)
讲解之前我必须先安利个网站模客,在学习Retrofit之前,各种网络请求如果想学习的话就必须有接口才能访问,Get请求还好说,但遇到Post请求,自己发送的是啥也不清楚,苦于自己不会后端写接口,所以之前对Retrofit的学习要么是各种找现成的API,要么就只是照猫画虎的敲了下并没有实践,有了这个网站你就可以自己写接口自己访问来测测看Retrofit的运用到底对不对。
具体该网站的使用见模客的使用这篇文章,下面我们来学习Retrofit的使用吧
1. Retrofit的基本使用
1.1 添加依赖
//Retrofit implementation 'com.squareup.retrofit2:retrofit:2.5.0' //Gson converter implementation 'com.squareup.retrofit2:converter-gson:2.5.0' 复制代码
第二个依赖主要是对Json数据进行解析的。
1.2 实现步骤
- 创建网络请求的接口
- 创建Retrofit实例
- 创建网络请求接口的实例
- 发送网络请求
和官网一样,可以看下官网介绍的代码,就是上面所写的步骤
-
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"); 复制代码
1.3 具体实现
下面我将介绍个具体的例子,让没用过Retrofit的先熟悉下Retrofit如何使用
1.3.1 创建网络请求的接口
public interface GetApi { /** * 获取用户信息 * @return * @Query 注解 */ @GET("getUserInfo") Call<UserInfo> getUserInfo(@Query("id") String userId); } 复制代码
这个@Query注解是什么可以先不用管,下面会详细讲解。
UserInfo是我们得到返回数据的数据Bean类
1.3.2 创建Retrofit实例
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"),所以最终的访问地址为
http://mock-api.com/2vKVbXK8.mock/getUserInfo?id=userid
,此处的userid为自己传入的参数。
注意:baseUrl必须要以 /
结尾!!!
addConverterFactory:
加这个 addConverterFactory(GsonConverterFactory.create())
固定的,则会将返回的Json数据直接解析为我们的数据Bean类
1.3.3 创建网络请求接口的实例
private GetApi getApi; getApi = retrofit.create(GetApi.class); 复制代码
1.3.4 发送网络请求
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网络请求接口中主要有哪些注解。
2. Get请求
baseUrl为: http://mock-api.com/2vKVbXK8.mock/
2.1 @Query
访问地址
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
2.2 @QueryMap
访问地址
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); } }); 复制代码
2.3 @Path
访问地址
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类时可以用这个,这样,我们可以通过上述字符串的形式获取到返回的内容。
2.4 @Url
访问地址
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这里写什么都可以,没有以 /
结尾也可以
2.5 @Headers("")
静态添加头部信息:包含添加单个头部、添加多个头部
通过@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(); 复制代码
模客后台
通过观察模客模拟器的匹配日志,可以看到我们访问时确实加上了头部信息
2.6 @Header
动态添加单个头部信息
访问地址
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的信息。
2.7 @HeaderMap
动态添加多个头部信息
访问地址
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中
3. Post请求
对比着Get请求中的注解,Post请求中的注解就很好记了。
@Field 对应 @Query
@FieldMap 对应 @QueryMap
@Body 对应 @Url
注意
在Post请求中,尽量不要使用@Query和@QueryMap,因为它传入的参数是直接拼接在url上的,不安全,而@Field和@FieldMap是写入到Body中的。
3.1 @FormUrlEncoded
@FormUrlEncoded
用于修饰 @Field
注解和 @FieldMap
注解,将会自动将请求参数的类型调整为
application/x-www-form-urlencoded
3.2 @Field
访问地址
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后面
这里是根据我们设立的规则来进行匹配的,当然我们也可以选择文本或其他的方式进行匹配。
3.3 @FieldMap
访问地址
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.4 @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 复制代码
3.5 @Part/@PartMap
这两个注解和文件上传相关,在后面的文章中会进行详细讲解。
4. 注意
-
访问地址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 复制代码
5. 总结
以上就是关于Retrofit的一些注解的基本使用介绍,具体代码见 Github .
为了简便观察,文章中只是使用了一个注解来建立接口,其实在实际使用时,可以多个注解连用,例如下面所示:
@GET("api/{param}/getUserInfo") Call<UserInfo> getUserInfo(@Path("params") String param, @Query("id") String userId); 复制代码
具体怎么结合还是要根据实际项目提供的url来使用。以上就是全部内容,能力有限,不对的地方还望指出,有帮助的话还望点个start,下篇文章见。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Java注解Annotation与自定义注解详解
- springmvc教程--注解开发基础详解
- Spring IoC 公共注解详解
- spring mvc 常用注解详解
- 「Java笔记」 详解 Spring 注解 @Autowired
- Java中lombok @Builder注解使用详解
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。