使用项目的原话:Android和Java中类型安全的HTTP客户端
项目地址:https://github.com/square/retrofit
这里Retrofit还需要导入它的Gson依赖库,因为返回的数据需要Gson来处理
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
1、Get请求
2、Post请求
3、单、多文件上传
演示提供的接口(该接口不支持post方式)
http://japi.juhe.cn/joke/content/list.from?key=488c65f3230c0280757b50686d1f1cd5&&sort=asc&&time=1418816972
get请求(支持普通请求)
/*
* Get请求
* 参数已经封装在工具类的Url中
*/
Call call = RetrofitUtils.getInstance().get();
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
}
@Override
public void onFailure(Call call, Throwable t) {
}
});
get请求(支持键值对参数)
//根据接口需求创建键值对
Map map = new HashMap<>();
map.put("key","488c65f3230c0280757b50686d1f1cd5");
map.put("sort","asc");
map.put("time","1418816972");
/*
* Get请求
* @param map 为get参数
*/
Call call = RetrofitUtils.getInstance().get(map);
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
}
@Override
public void onFailure(Call call, Throwable t) {
}
});
Post请求(支持键值对参数)
//根据接口需求创建键值对
Map map = new HashMap<>();
map.put("key","488c65f3230c0280757b50686d1f1cd5");
map.put("sort","asc");
map.put("time","1418816972");
/*
* Post请求
* @param map 为Post参数
*/
Call call = RetrofitUtils.getInstance().post(map);
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
}
@Override
public void onFailure(Call call, Throwable t) {
}
});
Post请求(支持获取返回的字符串)
//根据接口需求创建键值对
Map<String,String> map = new HashMap<>();
map.put("key","488c65f3230c0280757b50686d1f1cd5");
map.put("sort","asc");
map.put("time","1418816972");
/*
* Post请求
* @param map 为Post参数
*/
Call<ResponseBody> call = RetrofitUtils.getInstance().post(map);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
//这里采用Retrofit2自带的ResponseBody可以返回对应的字符串数据,get请求同理
String body = response.body().string().toString();
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
Post请求(上传文件和参数)
//文件的封装
List parts = null;
parts = RetrofitUtils.filesToMultipartBodyParts("imgs[]", photo_list);
//参数的封装
Map params = new HashMap<>();
params.put("token", RetrofitUtils.convertToRequestBody("abcdefg"));
params.put("username", RetrofitUtils.convertToRequestBody("hensen"));
params.put("password", RetrofitUtils.convertToRequestBody("123456"));
//上传文件和参数
Call
Retrofit的请求是以REST请求方式发送请求的,所以工具的封装需要做两件事
由于我们接口返回的JSON数据如下
{
"error_code": 0,
"reason": "Success",
"result": {
"data":[
{
"content":"学校论坛上有人问:“为啥明明用了除蟑螂的药,蟑螂却越来越多了。”某个学生回帖:“如果你家人不见了,你不出来找吗?你会不着急么?”",
"hashId":"8196907ee902f3508b9be6ea59d2191c",
"unixtime":1478598830,
"updatetime":"2016-11-08 17:53:50"
}
]
}
}
所以这里需要对我们需要解析的数据进行Bean对象的封装
public class Info {
@Override
public String toString() {
return "Info{" +
"error_code=" + error_code +
", reason='" + reason + '\'' +
", result=" + result +
'}';
}
private int error_code;
private String reason;
private ResultBean result;
public static class ResultBean {
@Override
public String toString() {
return "ResultBean{" +
"data=" + data +
'}';
}
private List data;
public static class DataBean {
private String content;
private String hashId;
private int unixtime;
private String updatetime;
@Override
public String toString() {
return "DataBean{" +
"content='" + content + '\'' +
", hashId='" + hashId + '\'' +
", unixtime=" + unixtime +
", updatetime='" + updatetime + '\'' +
'}';
}
}
}
}
Retrofit使用注解的方式来声明GET请求、POST请求、请求参数、请求头等进行的网络访问,下面是各个注解的表示的意思
Get请求相关
Post请求相关
Header请求相关
Path请求相关
理解完意思之后,编写REST的API,其实就是请求接口,具体看下面的代码
public interface IRetrofitServer {
String getUrl = "list.from";
String postUrl = "list.from";
/**
* 传递参数的Get请求
* @param key
* @param sort
* @param time
* @return
*/
@GET(getUrl)
Call get(@Query("key") String key, @Query("sort") String sort, @Query("time") String time);
/**
* 封装好Url的Get的请求
* @return
*/
@GET(getUrl + "?key=488c65f3230c0280757b50686d1f1cd5&&sort=asc&&time=1418816972")
Call get();
/**
* 传递Map键值对的Get请求
* @param params
* @return
*/
@GET(getUrl)
Call get(@QueryMap Map params);
/**
* 传递参数的Post请求
* @param key
* @param sort
* @param time
* @return
*/
@FormUrlEncoded
@POST(postUrl)
Call post(@Field("key") String key, @Field("sort") String sort, @Field("time") String time);
/**
* 传递Map键值对的Post请求
* @param map
* @return
*/
@FormUrlEncoded
@POST(postUrl)
Call post(@FieldMap Map map);
/**
* 传递Map键值对的Post请求
* @param map
* @return 对应的字符串数据
*/
@FormUrlEncoded
@POST(postUrl)
Call post(@FieldMap Map map);
/**
* 传递Map键值对和Header的Post请求
* @param key
* @param sort
* @param time
* @return
*/
@Headers({"os:Android", "version:2.0"})
@FormUrlEncoded
@POST(postUrl)
Call postWithHeader(@Field("key") String key, @Field("sort") String sort, @Field("time") String time);
/**
* 传递Map键值对和Header的Post请求
* @param os
* @param key
* @param sort
* @param time
* @return
*/
@FormUrlEncoded
@POST(postUrl)
Call postWithHeader(@Header("os") String os, @Field("key") String key, @Field("sort") String sort, @Field("time") String time);
/**
* 传递Map键值对和Header的Post请求
* @param map
* @param key
* @param sort
* @param time
* @return
*/
@FormUrlEncoded
@POST(postUrl)
Call postWithHeader(@HeaderMap Map map, @Field("key") String key, @Field("sort") String sort, @Field("time") String time);
/**
* 传递访问路径和键值对的Post请求
* @param path
* @param key
* @param sort
* @param time
* @return
*/
@FormUrlEncoded
@POST("{path}")
Call post(@Path("path") String path, @Field("key") String key, @Field("sort") String sort, @Field("time") String time);
}
Retrofit和okHttp一样,采用构造者模式创建,采用单例模式防止使用多个对象
private static final String baseUrl = "http://japi.juhe.cn/joke/content/";
private static Retrofit retrofit = null;
private static IRetrofitServer iServer;
public static IRetrofitServer getInstance() {
if (retrofit == null) {
synchronized (RetrofitUtils.class) {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
iServer = retrofit.create(IRetrofitServer.class);
}
}
}
return iServer;
}
上面代码做了三件事
下面就可以直接使用工具类拿到这个iServer,调用提供的接口方法
Call call = RetrofitUtils.getInstance().get();
call.enqueue(...);
API接口的创建,比如说注册功能,需要上传两张身份证照片,这是我自己服务器的接口
public interface IRetrofitServer {
@Multipart
@POST("app/register")
Call register(@PartMap Map map, @Part List parts);
}
创建两个方法辅助PartMap和Part的创建
//这里的key则是后台服务器的字段名,即使H5中input的name的名字
//如果是单文件,filePaths的大小就为1
public static List filesToMultipartBodyParts(String key, List filePaths) {
List parts = new ArrayList<>(filePaths.size());
for (String filePath : filePaths) {
File file = new File(filePath);
//这里的image/*表示上传的是相片的所有格式,你可以替换成你需要的格式
RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part part = MultipartBody.Part.createFormData(key, file.getName(), requestBody);
parts.add(part);
}
return parts;
}
public static RequestBody convertToRequestBody(String param) {
//这里的text/plain表示参数都是文本
RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"), param);
return requestBody;
}
到这里,你就可以回过头去看下文章开头的演示部分,那里就是RetrofitUtils的使用
由于文件上传是我在做项目的时候用上的,工具类缺少文件上传的内容,大家可以自行去拷贝代码