@linux1s1s
2016-11-19T01:58:48.000000Z
字数 9798
阅读 2134
AndroidRefine 2016-11
系列博文
Android 开源库 - OkHttp
Android 开源库 - Retrofit
Android 开源库 - Okio
Android 开源库 - Fresco
我们用官网的一句话概括:
A type-safe HTTP client for Android and Java
Retrofit用来简化Client API请求,尤其适用于REST API
我们通过一个简单的demo来直观感受一下Retrofit,此damo使用
retrofit:2.1.0版本
build.gradle配置
// OkHttpcompile 'com.squareup.okhttp3:okhttp:3.4.2'// OkIocompile 'com.squareup.okio:okio:1.11.0'//Retrofitcompile 'com.squareup.retrofit2:retrofit:2.1.0'//Maven Address// https://mvnrepository.com/artifact/com.squareup.retrofit2///Converter: Gsoncompile group: 'com.squareup.retrofit2', name: 'converter-gson', version: '2.1.0'//Converter: Jackson// compile group: 'com.squareup.retrofit2', name: 'converter-jackson', version: '2.1.0'//Converter: Protocol Bufferscompile group: 'com.squareup.retrofit2', name: 'converter-protobuf', version: '2.1.0'//Converter: Wire Protocol Bufferscompile group: 'com.squareup.retrofit2', name: 'converter-wire', version: '2.1.0'//Converter: Moshicompile group: 'com.squareup.retrofit2', name: 'converter-moshi', version: '2.1.0'//Converter: SimpleXML// compile group: 'com.squareup.retrofit2', name: 'converter-simplexml', version: '2.1.0'//Converter: Java Scalarscompile group: 'com.squareup.retrofit2', name: 'converter-scalars', version: '2.1.0'
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"package="okhttp.mutex.com.okhttpdemo"><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>
补充说明:
- retrofit 2.1.0 依赖okHttp,而okHttp依赖okIo
- 需要选择至少一种Converter,这里选择Gson作为Converter
- retrofit提供了上面列出来的Converter,如果不满足你的要求,可以自己做扩展
为了验证retrofit,这里选择度娘最近低调发布的API Store,进一步选择天狗药店大全。
API简要说明如下:

JSON数据格式如下:
{"status": true,"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"}]}
然后做好POJO类,Android Studio可以利用插件GsonFormat快速生成,可以参考Android Studio Plugins
import java.io.Serializable;import java.util.List;public class Info implements Serializable {/*** status : true* 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"}]*/private boolean status;private List<TngouBean> tngou;public boolean isStatus() {return status;}public void setStatus(boolean status) {this.status = status;}public List<TngouBean> getTngou() {return tngou;}public void setTngou(List<TngouBean> tngou) {this.tngou = tngou;}public static class TngouBean {/*** 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*/private String address;private int area;private String business;private String charge;private int count;private long createdate;private int fcount;private int id;private String img;private String leader;private String legal;private String message;private String name;private String number;private int rcount;private int supervise;private String tel;private String type;private String url;private String waddress;private double x;private double y;private String zipcode;public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public int getArea() {return area;}public void setArea(int area) {this.area = area;}public String getBusiness() {return business;}public void setBusiness(String business) {this.business = business;}public String getCharge() {return charge;}public void setCharge(String charge) {this.charge = charge;}public int getCount() {return count;}public void setCount(int count) {this.count = count;}public long getCreatedate() {return createdate;}public void setCreatedate(long createdate) {this.createdate = createdate;}public int getFcount() {return fcount;}public void setFcount(int fcount) {this.fcount = fcount;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getImg() {return img;}public void setImg(String img) {this.img = img;}public String getLeader() {return leader;}public void setLeader(String leader) {this.leader = leader;}public String getLegal() {return legal;}public void setLegal(String legal) {this.legal = legal;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getNumber() {return number;}public void setNumber(String number) {this.number = number;}public int getRcount() {return rcount;}public void setRcount(int rcount) {this.rcount = rcount;}public int getSupervise() {return supervise;}public void setSupervise(int supervise) {this.supervise = supervise;}public String getTel() {return tel;}public void setTel(String tel) {this.tel = tel;}public String getType() {return type;}public void setType(String type) {this.type = type;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getWaddress() {return waddress;}public void setWaddress(String waddress) {this.waddress = waddress;}public double getX() {return x;}public void setX(double x) {this.x = x;}public double getY() {return y;}public void setY(double y) {this.y = y;}public String getZipcode() {return zipcode;}@Overridepublic String toString() {return "TngouBean{" +"address='" + address + '\'' +", area=" + area +", business='" + business + '\'' +", charge='" + charge + '\'' +", count=" + count +", createdate=" + createdate +", fcount=" + fcount +", id=" + id +", img='" + img + '\'' +", leader='" + leader + '\'' +", legal='" + legal + '\'' +", message='" + message + '\'' +", name='" + name + '\'' +", number='" + number + '\'' +", rcount=" + rcount +", supervise=" + supervise +", tel='" + tel + '\'' +", type='" + type + '\'' +", url='" + url + '\'' +", waddress='" + waddress + '\'' +", x=" + x +", y=" + y +", zipcode='" + zipcode + '\'' +'}';}public void setZipcode(String zipcode) {this.zipcode = zipcode;}}}
import retrofit2.Call;import retrofit2.http.GET;import retrofit2.http.Header;import retrofit2.http.Path;import retrofit2.http.Query;public interface StoreService {@GET("/tngou/{path}/name")Call<Info> getStoreResult(@Path("path") String path, @Header("apikey") String apiKey, @Query("name") String name);}
简单的分为三步,分别如下
创建Retrofit对象/获取Retrofit API请求/异步&同步发送请求
/*** 1. 创建Retrofit对象** @return*/private static Retrofit buildRetrofit() {return new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build();}
/*** 2. 获取Retrofit API请求** @return*/private static Call<Info> obtainCall() {Retrofit retrofit = buildRetrofit();StoreService service = retrofit.create(StoreService.class);return service.getStoreResult("store", API_KEY, NAME);}
/*** 3. 异步发送请求** @param context*/public static void enqueue(final Activity context) {Call<Info> call = obtainCall();if (call == null) return;call.enqueue(new Callback<Info>() {@Overridepublic void onResponse(Call<Info> call, Response<Info> response) {if (response.isSuccessful()) {final Info info = response.body();context.runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(context, "onResponse() Result is: " + info.getTngou().toString(), Toast.LENGTH_SHORT).show();}});}}@Overridepublic void onFailure(Call<Info> call, final Throwable t) {context.runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(context, "onFailure() " + t.getMessage(), Toast.LENGTH_SHORT).show();}});}});}
/*** Retrofit get方式请求API,异步,添加Header** @param view*/public void retrofitSendGetWithHeader(final View view) {new Thread() {@Overridepublic void run() {RetrofitUtil.enqueue(MainActivity.this);}}.start();}
app运行截图:
charles请求截图:

这里我们不再使用Retrofit给我们提供的Converter,而是直接获取OkHttp给我们的Raw数据,下面给个栗子。
import okhttp3.ResponseBody;import retrofit2.Call;import retrofit2.http.GET;import retrofit2.http.Header;import retrofit2.http.Path;import retrofit2.http.Query;public interface RawService {@GET("/tngou/{path}/name")Call<ResponseBody> getRawResult(@Path("path") String path, @Header("apikey") String apiKey, @Query("name") String name);}
/*** 1. 创建Retrofit对象** @return*/private static Retrofit buildRetrofit() {return new Retrofit.Builder().baseUrl(BASE_URL).build();}/*** 2. 获取Retrofit Raw API请求** @return*/private static Call<ResponseBody> obtainRawCall() {Retrofit retrofit = buildRetrofit();RawService service = retrofit.create(RawService.class);return service.getRawResult("store", API_KEY, NAME);}/*** 3. 异步发送请求** @param context*/public static void enqueueRaw(final Activity context) {Call<ResponseBody> call = obtainRawCall();if (call == null) return;try {Response<ResponseBody> response = call.execute();String result = response.body().string();Gson gson = new Gson();final Info info = gson.fromJson(result, Info.class);if (info != null) {context.runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(context, "onResponse() Result is: " + info.getTngou().toString(), Toast.LENGTH_SHORT).show();}});} else {Toast.makeText(context, "onResponse() Result is: NULL", Toast.LENGTH_SHORT).show();}} catch (IOException e) {e.printStackTrace();}}
经过验证,使用RAW抛弃了Retrofit给我们提供的Converter便利,当然这里仅仅是验证可行性,读者可以自行参考选择哪种方式。
参考文章:
OkHttp GitHub Doc
Retrofit GitHub DocR Doc Maven
Fresco GitHub Doc
Okio GitHub Video