[关闭]
@linux1s1s 2016-11-19T09:58:48.000000Z 字数 9798 阅读 1756

Android 开源库 - Retrofit

AndroidRefine 2016-11


系列博文
Android 开源库 - OkHttp
Android 开源库 - Retrofit
Android 开源库 - Okio
Android 开源库 - Fresco

Retrofit是什么

我们用官网的一句话概括:
A type-safe HTTP client for Android and Java

为什么要用Retrofit

Retrofit用来简化Client API请求,尤其适用于REST API

如何使用

我们通过一个简单的demo来直观感受一下Retrofit,此damo使用retrofit:2.1.0版本

配置

build.gradle配置

  1. // OkHttp
  2. compile 'com.squareup.okhttp3:okhttp:3.4.2'
  3. // OkIo
  4. compile 'com.squareup.okio:okio:1.11.0'
  5. //Retrofit
  6. compile 'com.squareup.retrofit2:retrofit:2.1.0'
  7. //Maven Address
  8. // https://mvnrepository.com/artifact/com.squareup.retrofit2/
  9. //Converter: Gson
  10. compile group: 'com.squareup.retrofit2', name: 'converter-gson', version: '2.1.0'
  11. //Converter: Jackson
  12. // compile group: 'com.squareup.retrofit2', name: 'converter-jackson', version: '2.1.0'
  13. //Converter: Protocol Buffers
  14. compile group: 'com.squareup.retrofit2', name: 'converter-protobuf', version: '2.1.0'
  15. //Converter: Wire Protocol Buffers
  16. compile group: 'com.squareup.retrofit2', name: 'converter-wire', version: '2.1.0'
  17. //Converter: Moshi
  18. compile group: 'com.squareup.retrofit2', name: 'converter-moshi', version: '2.1.0'
  19. //Converter: SimpleXML
  20. // compile group: 'com.squareup.retrofit2', name: 'converter-simplexml', version: '2.1.0'
  21. //Converter: Java Scalars
  22. compile group: 'com.squareup.retrofit2', name: 'converter-scalars', version: '2.1.0'

AndroidManifest.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="okhttp.mutex.com.okhttpdemo">
  4. <uses-permission android:name="android.permission.INTERNET" />
  5. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  6. <application
  7. android:allowBackup="true"
  8. android:icon="@mipmap/ic_launcher"
  9. android:label="@string/app_name"
  10. android:supportsRtl="true"
  11. android:theme="@style/AppTheme">
  12. <activity android:name=".MainActivity">
  13. <intent-filter>
  14. <action android:name="android.intent.action.MAIN" />
  15. <category android:name="android.intent.category.LAUNCHER" />
  16. </intent-filter>
  17. </activity>
  18. </application>
  19. </manifest>

补充说明:

  • retrofit 2.1.0 依赖okHttp,而okHttp依赖okIo
  • 需要选择至少一种Converter,这里选择Gson作为Converter
  • retrofit提供了上面列出来的Converter,如果不满足你的要求,可以自己做扩展
选择测试API

为了验证retrofit,这里选择度娘最近低调发布的API Store,进一步选择天狗药店大全

  1. {
  2. "status": true,
  3. "tngou": [{
  4. "address": "浦东新区周浦镇康沈路2578号",
  5. "area": 3,
  6. "business": "中成药、化学药制剂、抗生素、生化药品、生物制品",
  7. "charge": "张杰",
  8. "count": 80,
  9. "createdate": 1347984000000,
  10. "fcount": 0,
  11. "id": 79037,
  12. "img": "/store/081302/1d2a3c03ff722604bb6abd1e15c61a4c.jpg",
  13. "leader": "李赢",
  14. "legal": "李金锋",
  15. "message": "",
  16. "name": "上海好药师德高药店",
  17. "number": "沪CA0140423",
  18. "rcount": 0,
  19. "supervise": 12,
  20. "tel": "",
  21. "type": "零售连锁企业加盟店",
  22. "url": "",
  23. "waddress": "****** ;",
  24. "x": 121.582,
  25. "y": 31.0968,
  26. "zipcode": "200001"
  27. }]
  28. }
生成POJO

然后做好POJO类,Android Studio可以利用插件GsonFormat快速生成,可以参考Android Studio Plugins

  1. import java.io.Serializable;
  2. import java.util.List;
  3. public class Info implements Serializable {
  4. /**
  5. * status : true
  6. * tngou : [{"address":"浦东新区周浦镇康沈路2578号","area":3,"business":"中成药、化学药制剂、抗生素、生化药品、生物制品","charge":"张杰","count":80,"createdate":1347984000000,"fcount":0,"id":79037,"img":"/store/081302/1d2a3c03ff722604bb6abd1e15c61a4c.jpg","leader":"李赢","legal":"李金锋","message":"","name":"上海好药师德高药店","number":"沪CA0140423","rcount":0,"supervise":12,"tel":"","type":"零售连锁企业加盟店","url":"","waddress":"****** ;","x":121.582,"y":31.0968,"zipcode":"200001"}]
  7. */
  8. private boolean status;
  9. private List<TngouBean> tngou;
  10. public boolean isStatus() {
  11. return status;
  12. }
  13. public void setStatus(boolean status) {
  14. this.status = status;
  15. }
  16. public List<TngouBean> getTngou() {
  17. return tngou;
  18. }
  19. public void setTngou(List<TngouBean> tngou) {
  20. this.tngou = tngou;
  21. }
  22. public static class TngouBean {
  23. /**
  24. * address : 浦东新区周浦镇康沈路2578号
  25. * area : 3
  26. * business : 中成药、化学药制剂、抗生素、生化药品、生物制品
  27. * charge : 张杰
  28. * count : 80
  29. * createdate : 1347984000000
  30. * fcount : 0
  31. * id : 79037
  32. * img : /store/081302/1d2a3c03ff722604bb6abd1e15c61a4c.jpg
  33. * leader : 李赢
  34. * legal : 李金锋
  35. * message :
  36. * name : 上海好药师德高药店
  37. * number : 沪CA0140423
  38. * rcount : 0
  39. * supervise : 12
  40. * tel :
  41. * type : 零售连锁企业加盟店
  42. * url :
  43. * waddress : ****** ;
  44. * x : 121.582
  45. * y : 31.0968
  46. * zipcode : 200001
  47. */
  48. private String address;
  49. private int area;
  50. private String business;
  51. private String charge;
  52. private int count;
  53. private long createdate;
  54. private int fcount;
  55. private int id;
  56. private String img;
  57. private String leader;
  58. private String legal;
  59. private String message;
  60. private String name;
  61. private String number;
  62. private int rcount;
  63. private int supervise;
  64. private String tel;
  65. private String type;
  66. private String url;
  67. private String waddress;
  68. private double x;
  69. private double y;
  70. private String zipcode;
  71. public String getAddress() {
  72. return address;
  73. }
  74. public void setAddress(String address) {
  75. this.address = address;
  76. }
  77. public int getArea() {
  78. return area;
  79. }
  80. public void setArea(int area) {
  81. this.area = area;
  82. }
  83. public String getBusiness() {
  84. return business;
  85. }
  86. public void setBusiness(String business) {
  87. this.business = business;
  88. }
  89. public String getCharge() {
  90. return charge;
  91. }
  92. public void setCharge(String charge) {
  93. this.charge = charge;
  94. }
  95. public int getCount() {
  96. return count;
  97. }
  98. public void setCount(int count) {
  99. this.count = count;
  100. }
  101. public long getCreatedate() {
  102. return createdate;
  103. }
  104. public void setCreatedate(long createdate) {
  105. this.createdate = createdate;
  106. }
  107. public int getFcount() {
  108. return fcount;
  109. }
  110. public void setFcount(int fcount) {
  111. this.fcount = fcount;
  112. }
  113. public int getId() {
  114. return id;
  115. }
  116. public void setId(int id) {
  117. this.id = id;
  118. }
  119. public String getImg() {
  120. return img;
  121. }
  122. public void setImg(String img) {
  123. this.img = img;
  124. }
  125. public String getLeader() {
  126. return leader;
  127. }
  128. public void setLeader(String leader) {
  129. this.leader = leader;
  130. }
  131. public String getLegal() {
  132. return legal;
  133. }
  134. public void setLegal(String legal) {
  135. this.legal = legal;
  136. }
  137. public String getMessage() {
  138. return message;
  139. }
  140. public void setMessage(String message) {
  141. this.message = message;
  142. }
  143. public String getName() {
  144. return name;
  145. }
  146. public void setName(String name) {
  147. this.name = name;
  148. }
  149. public String getNumber() {
  150. return number;
  151. }
  152. public void setNumber(String number) {
  153. this.number = number;
  154. }
  155. public int getRcount() {
  156. return rcount;
  157. }
  158. public void setRcount(int rcount) {
  159. this.rcount = rcount;
  160. }
  161. public int getSupervise() {
  162. return supervise;
  163. }
  164. public void setSupervise(int supervise) {
  165. this.supervise = supervise;
  166. }
  167. public String getTel() {
  168. return tel;
  169. }
  170. public void setTel(String tel) {
  171. this.tel = tel;
  172. }
  173. public String getType() {
  174. return type;
  175. }
  176. public void setType(String type) {
  177. this.type = type;
  178. }
  179. public String getUrl() {
  180. return url;
  181. }
  182. public void setUrl(String url) {
  183. this.url = url;
  184. }
  185. public String getWaddress() {
  186. return waddress;
  187. }
  188. public void setWaddress(String waddress) {
  189. this.waddress = waddress;
  190. }
  191. public double getX() {
  192. return x;
  193. }
  194. public void setX(double x) {
  195. this.x = x;
  196. }
  197. public double getY() {
  198. return y;
  199. }
  200. public void setY(double y) {
  201. this.y = y;
  202. }
  203. public String getZipcode() {
  204. return zipcode;
  205. }
  206. @Override
  207. public String toString() {
  208. return "TngouBean{" +
  209. "address='" + address + '\'' +
  210. ", area=" + area +
  211. ", business='" + business + '\'' +
  212. ", charge='" + charge + '\'' +
  213. ", count=" + count +
  214. ", createdate=" + createdate +
  215. ", fcount=" + fcount +
  216. ", id=" + id +
  217. ", img='" + img + '\'' +
  218. ", leader='" + leader + '\'' +
  219. ", legal='" + legal + '\'' +
  220. ", message='" + message + '\'' +
  221. ", name='" + name + '\'' +
  222. ", number='" + number + '\'' +
  223. ", rcount=" + rcount +
  224. ", supervise=" + supervise +
  225. ", tel='" + tel + '\'' +
  226. ", type='" + type + '\'' +
  227. ", url='" + url + '\'' +
  228. ", waddress='" + waddress + '\'' +
  229. ", x=" + x +
  230. ", y=" + y +
  231. ", zipcode='" + zipcode + '\'' +
  232. '}';
  233. }
  234. public void setZipcode(String zipcode) {
  235. this.zipcode = zipcode;
  236. }
  237. }
  238. }
定义接口
  1. import retrofit2.Call;
  2. import retrofit2.http.GET;
  3. import retrofit2.http.Header;
  4. import retrofit2.http.Path;
  5. import retrofit2.http.Query;
  6. public interface StoreService {
  7. @GET("/tngou/{path}/name")
  8. Call<Info> getStoreResult(@Path("path") String path, @Header("apikey") String apiKey, @Query("name") String name);
  9. }
Retrofit使用

简单的分为三步,分别如下创建Retrofit对象/获取Retrofit API请求/异步&同步发送请求

创建Retrofit对象
  1. /**
  2. * 1. 创建Retrofit对象
  3. *
  4. * @return
  5. */
  6. private static Retrofit buildRetrofit() {
  7. return new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build();
  8. }
获取Retrofit API请求
  1. /**
  2. * 2. 获取Retrofit API请求
  3. *
  4. * @return
  5. */
  6. private static Call<Info> obtainCall() {
  7. Retrofit retrofit = buildRetrofit();
  8. StoreService service = retrofit.create(StoreService.class);
  9. return service.getStoreResult("store", API_KEY, NAME);
  10. }
异步发送请求
  1. /**
  2. * 3. 异步发送请求
  3. *
  4. * @param context
  5. */
  6. public static void enqueue(final Activity context) {
  7. Call<Info> call = obtainCall();
  8. if (call == null) return;
  9. call.enqueue(new Callback<Info>() {
  10. @Override
  11. public void onResponse(Call<Info> call, Response<Info> response) {
  12. if (response.isSuccessful()) {
  13. final Info info = response.body();
  14. context.runOnUiThread(new Runnable() {
  15. @Override
  16. public void run() {
  17. Toast.makeText(context, "onResponse() Result is: " + info.getTngou().toString(), Toast.LENGTH_SHORT).show();
  18. }
  19. });
  20. }
  21. }
  22. @Override
  23. public void onFailure(Call<Info> call, final Throwable t) {
  24. context.runOnUiThread(new Runnable() {
  25. @Override
  26. public void run() {
  27. Toast.makeText(context, "onFailure() " + t.getMessage(), Toast.LENGTH_SHORT).show();
  28. }
  29. });
  30. }
  31. });
  32. }
TestCase
  1. /**
  2. * Retrofit get方式请求API,异步,添加Header
  3. *
  4. * @param view
  5. */
  6. public void retrofitSendGetWithHeader(final View view) {
  7. new Thread() {
  8. @Override
  9. public void run() {
  10. RetrofitUtil.enqueue(MainActivity.this);
  11. }
  12. }.start();
  13. }
验证结果

app运行截图:
此处输入图片的描述
charles请求截图:
此处输入图片的描述

绕开Retrofit,使用原生OkHttp

这里我们不再使用Retrofit给我们提供的Converter,而是直接获取OkHttp给我们的Raw数据,下面给个栗子。

接口
  1. import okhttp3.ResponseBody;
  2. import retrofit2.Call;
  3. import retrofit2.http.GET;
  4. import retrofit2.http.Header;
  5. import retrofit2.http.Path;
  6. import retrofit2.http.Query;
  7. public interface RawService {
  8. @GET("/tngou/{path}/name")
  9. Call<ResponseBody> getRawResult(@Path("path") String path, @Header("apikey") String apiKey, @Query("name") String name);
  10. }
使用Raw
  1. /**
  2. * 1. 创建Retrofit对象
  3. *
  4. * @return
  5. */
  6. private static Retrofit buildRetrofit() {
  7. return new Retrofit.Builder().baseUrl(BASE_URL).build();
  8. }
  9. /**
  10. * 2. 获取Retrofit Raw API请求
  11. *
  12. * @return
  13. */
  14. private static Call<ResponseBody> obtainRawCall() {
  15. Retrofit retrofit = buildRetrofit();
  16. RawService service = retrofit.create(RawService.class);
  17. return service.getRawResult("store", API_KEY, NAME);
  18. }
  19. /**
  20. * 3. 异步发送请求
  21. *
  22. * @param context
  23. */
  24. public static void enqueueRaw(final Activity context) {
  25. Call<ResponseBody> call = obtainRawCall();
  26. if (call == null) return;
  27. try {
  28. Response<ResponseBody> response = call.execute();
  29. String result = response.body().string();
  30. Gson gson = new Gson();
  31. final Info info = gson.fromJson(result, Info.class);
  32. if (info != null) {
  33. context.runOnUiThread(new Runnable() {
  34. @Override
  35. public void run() {
  36. Toast.makeText(context, "onResponse() Result is: " + info.getTngou().toString(), Toast.LENGTH_SHORT).show();
  37. }
  38. });
  39. } else {
  40. Toast.makeText(context, "onResponse() Result is: NULL", Toast.LENGTH_SHORT).show();
  41. }
  42. } catch (IOException e) {
  43. e.printStackTrace();
  44. }
  45. }

经过验证,使用RAW抛弃了Retrofit给我们提供的Converter便利,当然这里仅仅是验证可行性,读者可以自行参考选择哪种方式。

参考文章:
OkHttp GitHub Doc
Retrofit GitHub DocR Doc Maven
Fresco GitHub Doc
Okio GitHub Video

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注