1.简单介绍
retrofit事实上就是对okhttp做了进一步一层封装优化。
我们仅仅须要通过简单的配置就能使用retrofit来进行网络请求了。
Retrofit能够直接返回Bean对象,比如假设我们进行一个网络接口的请求。返回来一串json字符串。那么这个时候一般我们都要拿到这个json字符串后进行解析得到相应的Bean对象,Retrofit仅仅要依赖一下Gson的转换库然后进行简单的配置就能够直接拿到Bean对象了,不须要我们自己去解析。
接触过OKHttp的人会发现,Retrofit和OKHttp的代码有些地方有很大的类似度。
他的性能很的棒,国外大牛(被墙了)已经做过測例如以下图:

看了这个图之后你有什么想法?
Talk is cheap, show me the code!
!
2.高速使用
在实际项目开发中get、post请求使用居多。那我们以get请求来做个入门小案例。
http://ip.taobao.com/service/getIpInfo.php?ip=8.8.8.8
以上连接是一个get请求方式。參数在地址后面使用“?”进行名值对的拼接。请求的结果是一个json字符串数据。例如以下
{"code":0,"data":{"country":"\u7f8e\u56fd","country_id":"US","area":"","area_id":"","region":"","region_id":"","city":"","city_id":"","county":"","county_id":"","isp":"","isp_id":"","ip":"8.8.8.8"}}
来个简单的Demo界面例如以下:
功能很easy,一个输入框输入IP地址,然后获取IP地址所在的国家。

1)环境的配置
如今预计很少人用eclipse做项目开发了。eclipse的方式就不另赘述了(GitHub上也是有jar依赖下载的)。我们这里的开发工具是用的Android Studio,在 GitHub项目地址:https://github.com/square/retrofit能够找到Gradle的依赖代码:
加入两个依赖:retrofit依赖。和gson转换器。
1compile 'com.squareup.retrofit2:retrofit:2.1.0'//眼下最新的版本号 2compile 'com.squareup.retrofit2:converter-gson:2.1.0'//加入好这个依赖后我们就能够进行数据转换器的配置了。retrofit内部就会帮我们去转换json字符串为Java对象
在AS里面的效果例如以下:

converter-gson依赖的版本号号与retrofit依赖版本号号保持一致。我们在GitHub上能够看到。他们在同一个project里面的。
2)代码
布局很easy就不另贴代码了。类也不多參看以下的包结构图

Retrofit操作步骤
① 先把接口返回来的数据bean对象写好。
能够直接使用工具转化。如GsonFormat工具
1public class IpInfo { 2 public int code; 3 public DataBean data; 4 5 public static class DataBean { 6 public String country; 7 public String country_id; 8 public String area; 9 public String area_id; 10 public String region; 11 public String region_id; 12 public String city; 13 public String city_id; 14 public String county; 15 public String county_id; 16 public String isp; 17 public String isp_id; 18 public String ip; 19 20 } 21 22}
② 定义API接口
一般来讲都是处理遵循RESTful接口规范的http接口,我们须要把接口转化为Java Interface。
1/** 2 * 这个接口就是普通的借口类,可是看到里面的方法来,会有一些注解定义相关的功能 3 * 如@GET定义请求方式为get请求方式,假设有參数能够使用@Query、@QueryMap定义 4 */ 5 6public interface IpService { 7 /** 8 * @return 固定返回值为Call。当中泛型指定是进行请求后返回终于得数据类型。
③ 初始化Retrofit,创建接口实例,进行异步请求
代码凝视灰常仔细了
1/** 2 *Retrofit简单有用案例 3 * 4 * 採用http://ip.taobao.com/service/getIpInfo.php?ip=202.178.10.2 地址进行查询 5 */ 6public class MainActivity extends AppCompatActivity { 7 8 public static final String baseUrl = "http://ip.taobao.com/service/"; 9 private TextView tvResult; 10 private EditText etIp; 11 12 IpService ipService; 13 14 @Override 15 protected void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 setContentView(R.layout.activity_main); 18 tvResult = (TextView) findViewById(R.id.tv_result); 19 etIp = (EditText) findViewById(R.id.et_ip); 20 21 initRetrofit(); 22 } 23 24 /** 25 * 初始化Retrofit实例。并创建接口类。 26 * 注意:IpService不须要我们去实现。直接Retrofit=类有create方法生成。 27 */ 28 private void initRetrofit() { 29 30 //创建Retrofit的实例,把Gson转换器设置下 31 Retrofit retrofit = new Retrofit 32 .Builder() 33 .baseUrl(baseUrl)//设置API的基础地址 34 .addConverterFactory(GsonConverterFactory.create())//设置后才才支持json字符串转化为Bean 35 .build(); 36 37 //使用Retrofit的create方法传入创建接口实例 38 ipService = retrofit.create(IpService.class); 39 } 40 41 /** 42 * 布局中查询button配置的点击事件 43 * @param view 44 */ 45 public void check(View view) { 46 47 String ip = etIp.getText().toString(); 48 if (TextUtils.isEmpty(ip)) { 49 Toast.makeText(this, "ip 不能为空", Toast.LENGTH_SHORT).show(); 50 return; 51 } 52 53 //调用接口声明的方法 54 Call<IpInfo> ipInfoCall = ipService.getIpInfo(ip); 55 56 //call能够直接调用异步方法。进行结果获取。须要传入接口回调Callback, 57 ipInfoCall.enqueue(new Callback<IpInfo>() { 58 @Override 59 public void onResponse(Call<IpInfo> call, Response<IpInfo> response) { 60 //推断网络请求是否成功。网络请求返回code为[200..300)那么与后台连接成功。否则连接失败 61 if (response.isSuccessful()) { 62 //直接拿到JavaBean 63 IpInfo ipInfo = response.body(); 64 65 //这里直接能够进行UI操作。OKHttp是不行的哦 66 tvResult.setText(ipInfo.getData().getCountry()); 67 68 } else { 69 //请求失败。
3.经常使用注解
GET:get 请求方式
POST:post请求方式
Query:定义get请求參数
QueryMap:定义get请求參数
Field:定义post请求參数
FieldMap:定义post请求參数
Header:定义头參数
HeaderMap:定义头參数
Headers:定义头參数
Path:动态路径
来看看代码是怎么实现的:
1public interface SampleApi { 2 3//----------------------GET 请求方式 start -------------------------------- 4 /** 5 * 注解:GET。QUERY,QUERYMAP 的使用 6 */ 7 8 /** 9 * get 请求固定參数形式 10 * 11 * @return 12 */ 13 @GET("demo?username=zhanghsan&password=123455") 14 Call<SampleResponse> getFun(); 15 16 /** 17 * 使用@Query注解进行參数传递 18 * 19 * @param username 20 * @param password 21 * @return 22 */ 23 @GET("demo") 24 Call<SampleResponse> getFun(@Query("username") String username, @Query("password") String password); 25 26 /** 27 * 使用@QueryMap注解 Map集合进行參数传递 28 * 29 * @param params 30 * @return 31 */ 32 @GET("demo") 33 Call<SampleResponse> getFun(@QueryMap Map<String, Object> params); 34 35 36//----------------------GET 请求方式 end -------------------------------- 37 38 39//----------------------POST 请求方式 start -------------------------------- 40 /** 41 * POST,Field,FieldMap,FormUrlEncoded(POST 方式请求有參数的时候一定不要忘记了这个注解) 42 */ 43 44 /** 45 * post使用@Query注解进行參数传递 46 * 47 * @param username 48 * @param password 49 * @return 50 */ 51 @FormUrlEncoded 52 @POST("demo") 53 Call<SampleResponse> postFun(@Field("username") String username, @Field("password") String password); 54 55 /** 56 * POST使用@FiledMap Map集合进行參数传递 57 * 58 * @param params 59 * @return 60 */ 61 @FormUrlEncoded 62 @POST("demo") 63 Call<SampleResponse> postFun(@FieldMap Map<String, Object> params); 64 65 66//----------------------POST 请求方式 end -------------------------------- 67 68//----------------------head參数加入start -------------------------------- 69 70 /** 71 * Headers。Header,HeaderMap 72 * */ 73 74 /** 75 * 有些接口须要传送一些操作client系统的信息,比方系统类型。系统版本号等例如以下 76 * 77 * @param username 78 * @param password 79 * @return 80 */ 81 @Headers( 82 {"os:Android" 83 , "osversion:5.0" 84 }) 85 @FormUrlEncoded 86 @POST("demo") 87 Call<SampleResponse> postFunWithHead(@Field("username") String username, @Field("password") String password); 88 89 /** 90 * 有些接口须要传送一些操作client系统的信息,比方系统类型。系统版本号等例如以下 91 * 92 * @param username 93 * @param password 94 * @return 95 */ 96 @FormUrlEncoded 97 @POST("demo") 98 Call<SampleResponse> postFunWithHead(@Header("os") String os, @Header("osversion") String osversion, @Field("username") String username, @Field("password") String password); 99 100 /** 101 * 有些接口须要传送一些操作client系统的信息,比方系统类型,系统版本号等例如以下 102 * 103 * @param headParams head 參数。键值对的形式存储到map集合中去 104 * @param username 105 * @param password 106 * @return 107 */ 108 @FormUrlEncoded 109 @POST("demo") 110 Call<SampleResponse> postFunWithHead(@HeaderMap Map<String, String> headParams, @Field("username") String username, @Field("password") String password); 111 112//----------------------head參数加入end -------------------------------- 113 114//----------------------path 注解 -------------------------------- 115 116 /** 117 * Path注解使用时在请求方式注解后面的URL设置一个占位符,使用大括号包裹。
Activity代码
1public class SampleActivity extends AppCompatActivity { 2 EditText etName; 3 EditText etPassword; 4 TextView tvResult; 5 SampleApi sampleApi; 6 SampleCallBack callback; 7 8 @Override 9 protected void onCreate(Bundle savedInstanceState) { 10 super.onCreate(savedInstanceState); 11 setContentView(R.layout.activity_sample); 12 13 etName = (EditText) findViewById(R.id.et_name); 14 etPassword = (EditText) findViewById(R.id.et_password); 15 tvResult = (TextView) findViewById(R.id.tv_result); 16 17 //使用链式调用建立 18 sampleApi = new Retrofit 19 .Builder() 20 .baseUrl("http://10.0.2.2:8080/") 21 .addConverterFactory(GsonConverterFactory.create()) 22 .build() 23 .create(SampleApi.class); 24 25 callback = new SampleCallBack(); 26 27 28 } 29 30 31 /** 32 * button点击事件 33 * 34 * @param view 35 */ 36 public void submit(View view) { 37 tvResult.setText("正在请求...."); 38 39 String name = etName.getText().toString(); 40 String password = etPassword.getText().toString(); 41 42 if (TextUtils.isEmpty(name) || TextUtils.isEmpty(password)) { 43 Toast.makeText(this, "參数不能为空", Toast.LENGTH_SHORT).show(); 44 return; 45 } 46 Call<SampleResponse> call; 47 switch (view.getId()) { 48 case R.id.btn_get: 49 call = sampleApi.getFun(name, password); 50 call.enqueue(callback); 51 break; 52 case R.id.btn_post: 53 call = sampleApi.postFun(name, password); 54 call.enqueue(callback); 55 break; 56 case R.id.btn_head: 57// call = sampleApi.postFunWithHead(name, password);//第一种,直接静态定义方式。看接口方法 58// call = sampleApi.postFunWithHead("ios","10.10.10",name, password);//另外一种,能够动态配置值得方式 59 Map<String, String> map = new HashMap<>(); 60 map.put("os", "android"); 61 map.put("osversion", "9.9.9999999"); 62// call = sampleApi.postFunWithHead(map, name, password);//第三种,能够动态配置參数和值得形式 63 call = sampleApi.postFunWithHead("demo",map, name, password);//第四种,结合Path定义路径 64 call.enqueue(callback); 65 break; 66 } 67 } 68 69 70 /** 71 * @param result 72 * 显示结果 73 */ 74 public void showResult(String result) { 75 tvResult.setText(result); 76 } 77 78 79 /** 80 * 回调实现类 81 */ 82 public class SampleCallBack implements Callback<SampleResponse> { 83 @Override 84 public void onResponse(Call<SampleResponse> call, Response<SampleResponse> response) { 85 //推断网络请求是否成功。网络请求返回code为[200..300)那么与后台连接成功。否则连接失败 86 if (response.isSuccessful()) { 87 //直接拿到JavaBean 88 SampleResponse sampleResponse = response.body(); 89 90 //这里直接能够进行UI操作。OKHttp是不行的哦 91 showResult(sampleResponse.toString()); 92 93 } else { 94 //请求失败。
执行效果

4.URL操作注意事项
拼接注意,建议baseUrl用“/”结尾。接口中请求方式后面的url不用”/”开头
样例:baseUrl=http://10.0.2.2:8080/market/ url=home
错误案例
案例一:
baseUrl=http://10.0.2.2:8080/market url=home
—>http://10.0.2.2:8080/home
分析:默认用最后一个斜线去拼接
案例二:
baseUrl=http://10.0.2.2:8080/market url=/home
—>http://10.0.2.2:8080/home
分析:url中開始的斜线代表主机地址http://10.0.2.2:8080
Retrofit还能够实现上传下载以及 结合RxJava使用,等下回分解!