Retrofit源码解析(上)

Stella981
• 阅读 573

简介
Retrofit是Square公司开发的一款针对Android网络请求的框架,官网地址http://square.github.io/retrofit/ ,在官网上有这样的一句话介绍retrofit,A type-safe HTTP client for Android and Java。我们知道Retrofit底层是基于OKHttp实现的。对okhttp不了解的同学可以看看这一篇文章。okhttp源码解析https://www.cnblogs.com/huangjialin/p/9469373.html

okhttp简单使用

build.gradle依赖

1 implementation 'com.squareup.retrofit2:retrofit:2.4.0'
2 implementation 'com.squareup.retrofit2:converter-scalars:2.4.0'
3 implementation ‘com.squareup.retrofit2:converter-gson:2.4.0'

创建请求接口

 1 /**
 2  * Created by huangjialin on 2018/8/16.
 3  */
 4 
 5 public interface ApiService {
 6 
 7     @GET("api//Client/GetIsOpen")
 8     Call<SwitchTest> getInformation();
 9 
10 }

这里以GET请求为例,POST请求后面还会提。接口只是为了测试用,返回什么数据,不要在意。接下来看配置Retrofit

 1 package com.example.huangjialin.retrofittest;
 2 
 3 import android.os.Bundle;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.util.Log;
 6 import android.view.View;
 7 
 8 import retrofit2.Call;
 9 import retrofit2.Callback;
10 import retrofit2.Response;
11 import retrofit2.Retrofit;
12 import retrofit2.converter.gson.GsonConverterFactory;
13 import retrofit2.converter.scalars.ScalarsConverterFactory;
14 
15 public class MainActivity extends AppCompatActivity {
16 
17     @Override
18     protected void onCreate(Bundle savedInstanceState) {
19         super.onCreate(savedInstanceState);
20         setContentView(R.layout.activity_main);
21         findViewById(R.id.test).setOnClickListener(new View.OnClickListener() {
22             @Override
23             public void onClick(View view) {
24                 testRetrofit();
25             }
26         });
27     }
28 
29 
30     String url = "http://10.31.1.2:93";
31 
32     public void testRetrofit() {
33         //创建retrofit
34         Retrofit retrofit = new Retrofit.Builder()
35                 .baseUrl(url) //设置baseURl
36                 .addConverterFactory(ScalarsConverterFactory.create()) //增加返回值为String的支持
37                 .addConverterFactory(GsonConverterFactory.create())
38                 .build();
39         ApiService apiService = retrofit.create(ApiService.class);
40         Call<SwitchTest> call = apiService.getInformation();
41         call.enqueue(new Callback<SwitchTest>() {
42             @Override
43             public void onResponse(Call<SwitchTest> call, Response<SwitchTest> response) {
44                 Log.d("huangjialin", "---onResponse----" + response.body().getMessage());
45             }
46 
47             @Override
48             public void onFailure(Call<SwitchTest> call, Throwable t) {
49                 Log.d("huangjialin", "--- 失败----" );
50             }
51         });
52     }
53 }

Model类SwitchTest

 1 package com.example.huangjialin.retrofittest;
 2 
 3 /**
 4  * Created by huangjialin on 2018/8/16.
 5  */
 6 
 7 class SwitchTest {
 8     private String Message;
 9     private ModelBean Model;
10     private int ResultType;
11 
12     public String getMessage() {
13         return Message;
14     }
15 
16     public void setMessage(String message) {
17         Message = message;
18     }
19 
20     public ModelBean getModel() {
21         return Model;
22     }
23 
24     public void setModel(ModelBean model) {
25         Model = model;
26     }
27 
28     public int getResultType() {
29         return ResultType;
30     }
31 
32     public void setResultType(int resultType) {
33         ResultType = resultType;
34     }
35 
36     public static class ModelBean {
37         private boolean Phone;
38         private boolean Message;
39         private boolean ClientApp;
40 
41         public boolean isPhone() {
42             return Phone;
43         }
44 
45         public void setPhone(boolean phone) {
46             Phone = phone;
47         }
48 
49         public boolean isMessage() {
50             return Message;
51         }
52 
53         public void setMessage(boolean message) {
54             Message = message;
55         }
56 
57         public boolean isClientApp() {
58             return ClientApp;
59         }
60 
61         public void setClientApp(boolean clientApp) {
62             ClientApp = clientApp;
63         }
64     }
65 
66 }

最后记得加上网络权限

1 <uses-permission android:name=“android.permission.INTERNET"/>

retrofit一个简单的网络请求就可以了……当然,我这里的url是用我司的测试地址,是有网络权限的,所以记得替换成你们自己的地址。使用比较简单,这里不做过多的解释。下面我们看看retrofit的注解

请求方法

http请求方式一共有7种,分别是GET,POST、PUT、DELETE、HEAD、OPTIONS、PATCH,而其中我们最常用的就是get和post请求,这里也主要拿这两种方式分析。retrofit设置请求方法主要是通过注解的方式

get请求

1 @GET("api//Client/GetIsOpen")
2  Call<SwitchTest> getInformation();

post请求

1 @POST("api/login/GetModel")
2 Call<LoginModel> login(@Body Login login);

只需要在每个请求接口上方加上@GET(“aaaa”)或者是@POST(“aaaa”)就可以设置不同请求方式。retrofit除了可以通过注解的方式设置请求方法外,还可以通过注解来设置请求参数。

GET网络请求注解参数方式

@Query

1 @GET("api//Client/GetIsOpen")
2 Call<SwitchTest> getInformation(@Query("id") String id,@Query("page") int page);

这种方式会将这些请求参数附加到URL后面,也就是拼接起来。如上面设置的,最后会成为api//Client/GetIsOpen/id/page,当然,如果参数很多,可以使用下面这种方式

@QueryMap

1 @GET("api//Client/GetIsOpen")
2 Call<SwitchTest> getInformation(@QueryMap Map<String,String> parame);

这种方式可以将参数全部存放到Map中,源码中是这样解释QueryMap的Query parameter keys and values appended to the URL.意思是会将这个key值拼接到url上面。

除了可以拼接参数以外,还可以动态的拼接URL地址,使用@Path 

@Path

源码这样介绍Named replacement in a URL path segment. Values are converted to strings using

1 @GET("api//Client/{path}")
2 Call<SwitchTest> pathTest(@Path("path")String path);

这样我们在调用这个接口的时候,传入的参数就会替换这个path。

POST网络请求注解参数方式

我们知道,post请求的参数不是以拼接的形式的,而是将参数放到请求体中的,所以retrofit注解post请求的参数是以另外的方式

@Body

源码是这样解释的Use this annotation on a service method param when you want to directly control the request body,意思是当您想要直接控制请求体时,在服务方法参数上使用此注释

1 @POST("api/login/GetModel")
2 Call<LoginModel> login(@Body Login login);

其中Login是一个实体类,上面这个接口api/login/GetModel,是一个登陆接口,登陆就需要账号密码,所以这个实体类就可以这样设置。

 1 package com.example.huangjialin.retrofittest;
 2 
 3 /**
 4  * Created by huangjialin on 2018/8/16.
 5  */
 6 
 7 public class Login {
 8     private String tel;
 9     private String password;
10 
11     public Login(String tel, String password) {
12         this.tel = tel;
13         this.password = password;
14     }
15 }

当我们调用这个接口时,就可以传入new Login(“账号”,”密码”);

@Field

源码是这样解释的:Named pair for a form-encoded request.

1 @FormUrlEncoded
2 @POST("api/login/GetModel")
3 Call<LoginModel> login(@Field("tel") String tel,
4 @Field("password") String password);

这里需要注意一个地方使用@Field的时候,一定要记得加上@FormUrlEncoded,这个作用是表示请求主体将使用表单URL编码。

@FieldMap
源码是这样解释的:Named key/value pairs for a form-encoded request.翻译就是:表单编码请求的命名键/值对。简单一点的理解就是这样FieldMap可以将参数全部存放到map中。

1 @FormUrlEncoded
2 @POST("api/login/GetModel")
3 Call<LoginModel> login(@FieldMap Map<String,String>parame);

@Part

源码是这样解释的:Denotes a single part of a multi-part request.

1 @Multipart
2 @POST("user/photo")
3 Call<实体类> updateUser(@Part MultipartBody.Part photo, @Part("description") RequestBody description);

其中使用@Part 一定要记得加上@Multipart 源码是这样解释这个的Denotes that the request body is multi-part. Parts should be declared as parameters and annotated with {@link Part @Part}. 表示请求主体是多部分的。部件应该声明为参数和 注释为{@link Part @Part}。当然使用@Part 主要是用来上传文件的,并且是单文件上传的。如果多文件上传的话,可以使用下面这个

@PartMap

源码是这样解释的:Denotes name and value parts of a multi-part request.

1 @Multipart
2 @POST("user/photo")
3 Call<实体类> updateUser(@PartMap Map<String, RequestBody> photos,
4 @Part("description") RequestBody description);

除了上面这些注解外,我们往往还能看到这个注解

@Headers

1 @Headers("Cache-Control: max-age=640000")
2 @POST("api/login/GetModel")
3 Call<LoginModel> login(@Body Login login);

源码的解释和例子是这样的

 1 /**
 2  * Adds headers literally supplied in the {@code value}.
 3  * <pre><code>
 4  * &#64;Headers("Cache-Control: max-age=640000")
 5  * &#64;GET("/")
 6  * ...
 7  *
 8  * &#64;Headers({
 9  *   "X-Foo: Bar",
10  *   "X-Ping: Pong"
11  * })
12  * &#64;GET("/")
13  * ...
14  * </code></pre>
15  * <strong>Note:</strong> Headers do not overwrite each other. All headers with the same name will
16  * be included in the request.
17  *
18  * @see Header
19  * @see HeaderMap
20  */

有什么用的呢??在http请求中,为了防止攻击或是过滤掉不安全的访问或是添加特殊加密的访问等等,用来减轻服务器的压力和保证请求的安全等,就会在请求头上面加一些内容。

本来,想弄成一篇文章的,但是写完到这里以后,感觉篇幅好长,所以在这里分一下篇幅吧
Retrofit源码解析(下)https://www.cnblogs.com/huangjialin/p/9492271.html

点赞
收藏
评论区
推荐文章
秃头王路飞 秃头王路飞
4个月前
webpack5手撸vue2脚手架
webpack5手撸vue相信工作个12年的小伙伴们在面试的时候多多少少怕被问到关于webpack方面的知识,本菜鸟最近闲来无事,就尝试了手撸了下vue2的脚手架,第一次发帖实在是没有经验,望海涵。languageJavaScript"name":"vuecliversion2","version":"1.0.0","desc
浅梦一笑 浅梦一笑
4个月前
初学 Python 需要安装哪些软件?超级实用,小白必看!
编程这个东西是真的奇妙。对于懂得的人来说,会觉得这个工具是多么的好用、有趣,而对于小白来说,就如同大山一样。其实这个都可以理解,大家都是这样过来的。那么接下来就说一下python相关的东西吧,并说一下我对编程的理解。本人也是小白一名,如有不对的地方,还请各位大神指出01名词解释:如果在编程方面接触的比较少,那么对于软件这一块,有几个名词一定要了解,比如开发环
技术小男生 技术小男生
4个月前
linux环境jdk环境变量配置
1:编辑系统配置文件vi/etc/profile2:按字母键i进入编辑模式,在最底部添加内容:JAVAHOME/opt/jdk1.8.0152CLASSPATH.:$JAVAHOME/lib/dt.jar:$JAVAHOME/lib/tools.jarPATH$JAVAHOME/bin:$PATH3:生效配置
光头强的博客 光头强的博客
4个月前
Java面向对象试题
1、请创建一个Animal动物类,要求有方法eat()方法,方法输出一条语句“吃东西”。创建一个接口A,接口里有一个抽象方法fly()。创建一个Bird类继承Animal类并实现接口A里的方法输出一条有语句“鸟儿飞翔”,重写eat()方法输出一条语句“鸟儿吃虫”。在Test类中向上转型创建b对象,调用eat方法。然后向下转型调用eat()方
刚刚好 刚刚好
4个月前
css问题
1、在IOS中图片不显示(给图片加了圆角或者img没有父级)<div<imgsrc""/</divdiv{width:20px;height:20px;borderradius:20px;overflow:h
blmius blmius
1年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
小森森 小森森
4个月前
校园表白墙微信小程序V1.0 SayLove -基于微信云开发-一键快速搭建,开箱即用
后续会继续更新,敬请期待2.0全新版本欢迎添加左边的微信一起探讨!项目地址:(https://www.aliyun.com/activity/daily/bestoffer?userCodesskuuw5n)\2.Bug修复更新日历2.情侣脸功能大家不要使用了,现在阿里云的接口已经要收费了(土豪请随意),\\和注意
晴空闲云 晴空闲云
4个月前
css中box-sizing解放盒子实际宽高计算
我们知道传统的盒子模型,如果增加内边距padding和边框border,那么会撑大整个盒子,造成盒子的宽度不好计算,在实务中特别不方便。boxsizing可以设置盒模型的方式,可以很好的设置固定宽高的盒模型。盒子宽高计算假如我们设置如下盒子:宽度和高度均为200px,那么这会这个盒子实际的宽高就都是200px。但是当我们设置这个盒子的边框和内间距的时候,那
艾木酱 艾木酱
3个月前
快速入门|使用MemFire Cloud构建React Native应用程序
MemFireCloud是一款提供云数据库,用户可以创建云数据库,并对数据库进行管理,还可以对数据库进行备份操作。它还提供后端即服务,用户可以在1分钟内新建一个应用,使用自动生成的API和SDK,访问云数据库、对象存储、用户认证与授权等功能,可专
NVIDIA安培架构下MIG技术分析
关键词:NVIDIA、MIG、安培一什么是MIG2020年5月,NVIDIA发布了最新的GPU架构:安培,以及基于安培架构的最新的GPU:A100。安培提供了许多新的特性,MIG是其中一项非常重要的新特性。MIG的全名是MultiInstanceGPU。NVIDIA安培架构中的MIG模式可以在A100GPU上并行运行七个作业。多实
helloworld_28799839 helloworld_28799839
4个月前
常用知识整理
Javascript判断对象是否为空jsObject.keys(myObject).length0经常使用的三元运算我们经常遇到处理表格列状态字段如status的时候可以用到vue