@linux1s1s
2016-11-19T09:58:48.000000Z
字数 9798
阅读 1762
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配置
// OkHttp
compile 'com.squareup.okhttp3:okhttp:3.4.2'
// OkIo
compile 'com.squareup.okio:okio:1.11.0'
//Retrofit
compile 'com.squareup.retrofit2:retrofit:2.1.0'
//Maven Address
// https://mvnrepository.com/artifact/com.squareup.retrofit2/
//Converter: Gson
compile 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 Buffers
compile group: 'com.squareup.retrofit2', name: 'converter-protobuf', version: '2.1.0'
//Converter: Wire Protocol Buffers
compile group: 'com.squareup.retrofit2', name: 'converter-wire', version: '2.1.0'
//Converter: Moshi
compile 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 Scalars
compile 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" />
<application
android: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;
}
@Override
public 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>() {
@Override
public void onResponse(Call<Info> call, Response<Info> response) {
if (response.isSuccessful()) {
final Info info = response.body();
context.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(context, "onResponse() Result is: " + info.getTngou().toString(), Toast.LENGTH_SHORT).show();
}
});
}
}
@Override
public void onFailure(Call<Info> call, final Throwable t) {
context.runOnUiThread(new Runnable() {
@Override
public 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() {
@Override
public 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() {
@Override
public 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