Retrofit网络通信框架
Retrofit官方Github地址
github官方:retrofit
samples 目录有官方的调用例子
官方教程
引入Retrofit依赖:
//代码仓库地址
repositories {
maven { url 'https://oss.jfrog.org/libs-snapshot' }
}
//添加如下依赖
dependencies {
//Retrofit
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
//由于返回的数据为json类型,这里我们需要在studio中添加Gson的依赖:
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
}
数据源1采用百度反地理编码的web api
用chrome浏览器访问后的到的json数据,利用android studio 的GsonFormat 插件生成对应的实体类ReverseGeocodingResult
接口定义 --LocationService接口
为了进一步说明,我法说明的内容放在下面的代码中
/**
* Created by younghare on 2017/9/26.\
* Retrofit turns your HTTP API into a Java interface
*如
* http://api.map.baidu.com/telematics/v3/reverseGeocoding?location=116.3017193083,40.050743859593&coord_type=gcj02&output=json&ak=zUCOoHeth4BDeasrlkiGsTuHNeEfizxA&mcode=DB:92:E3:B4:54:9E:68:60:47:DD:0B:8A:75:3D:DA:E1:AB:91:DD:FB;czg.baidumapsdk.demo
* url参数
* version=v3
* funcType = reverseGeocoding
* url地址?后面的参数是
* location=地理坐标 如:116.3017193083,40.050743859593
* coord_type =编码 如: gcj02
* output = 输出格式 如:json
* ak =apkkey 如 :E4805d16520de693a3fe707cdc962045
* mcode =密钥 如:DB:92:E3:B4:54:9E:68:60:47:DD:0B:8A:75:3D:DA:E1:AB:91:DD:FB;czg.baidumapsdk.demo
*
*
*/
public interface LocationService {
static final String Host = "http://api.map.baidu.com/telematics/";
/**
* method 表示请求的方法,区分大小写
* path表示路径
* hasBody表示是否有请求体
*/
// @GET("v3/weather")
//包括@path参数(Url中多级目录参数)和@Query参数(Url?中带的参数)
@HTTP(method = "GET", path = "{version}/{funcType}", hasBody = false)
//url 中有参数用@Path引入 version =v3 ; funcType =reverseGeocoding
//url 参数在url ? 之后参数用 @Query引入
retrofit2.Call<ResponseBody> getReverseGeocoding(@Path("version") String version,@Path("funcType") String funcType,
@Query("location") String location, @Query("coord_type") String coord_type,
@Query("output") String output, @Query("ak") String ak,
@Query("mcode") String mcode
);
//没有Url中的path参数
@GET("reverseGeocoding")
retrofit2.Call<ResponseBody> getReverseGeocoding_noPath(
@Query("location") String location, @Query("coord_type") String coord_type,
@Query("output") String output, @Query("ak") String ak,
@Query("mcode") String mcode
);
}
包含@path和@query参数的调用方法
private void getDataByRetrofit() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(LocationService.Host)
.build();
LocationService locationService =retrofit.create(LocationService.class);
retrofit2.Call<ResponseBody> call = locationService.getReverseGeocoding(
"v3","reverseGeocoding",
"116.3017193083,40.050743859593","gcj02",
"json","E4805d16520de693a3fe707cdc962045",
"DB:92:E3:B4:54:9E:68:60:47:DD:0B:8A:75:3D:DA:E1:AB:91:DD:FB;czg.baidumapsdk.demo"
);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
}
只包含@Query的调用方法
private void getDataByRetrofit_noPath() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://api.map.baidu.com/telematics/v3/")
.build();
LocationService locationService =retrofit.create(LocationService.class);
retrofit2.Call<ResponseBody> call = locationService.getReverseGeocoding_noPath(
"116.3017193083,40.050743859593","gcj02",
"json","E4805d16520de693a3fe707cdc962045",
"DB:92:E3:B4:54:9E:68:60:47:DD:0B:8A:75:3D:DA:E1:AB:91:DD:FB;czg.baidumapsdk.demo"
);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
System.out.println(response.body().string());
Map<String, List<String>> map = response.headers().toMultimap();
System.out.println(map.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
}
很遗憾的是,虽然这样写属于正常,但百度的web api现在控制的越来越多了,
返回结果报错
{"status":220,"message":"APP Referer校验失败"}
或
{"status":240,"message":"APP 服务被禁用"}
具体原因参见:百度Web api通过定位获取当前城市的天气预报
没办法我用豆瓣的web api 再实现一下,校验一下正确性。
数据源2采用豆瓣的web api
选用下面这个接口不需要@Query参数哦
豆瓣Api V2 - 开发者
https://api.douban.com/v2/book/12220562
同样我们需要先数据模型Book
接口定义 --BookService
/**
* https://api.douban.com/v2/book/12220562
* url参数
* type=book
* bookId = 12220562
* url地址?后面的参数是---这里没有
*
*
*/
public interface BookService {
static final String Host = "https://api.douban.com/v2/";
/**
* method 表示请求的方法,区分大小写
* path表示路径
* hasBody表示是否有请求体
*/
@HTTP(method = "GET", path = "{type}/{bookId}", hasBody = false)
//url 中有参数用@Path引入 version =v3 ; funcType =reverseGeocoding
//url 参数在url ? 之后参数用 @Query引入
Call<ResponseBody> getBookInfo(@Path("type") String type, @Path("bookId") String bookId );
}
调用代码如下
//包含@path但没有@Query参数的调用方法
private void getDouBan_BookInfo() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BookService.Host)
.build();
BookService bookService =retrofit.create(BookService.class);
retrofit2.Call<ResponseBody> call = bookService.getBookInfo(
"book","12220562"
);
//call.execute(); //同步请求
//call.enqueue(callback); //异步请求
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
String bookInfoResult = response.body().string();
System.out.println(bookInfoResult);
Book book = new Gson().fromJson(bookInfoResult,Book.class);
System.out.println(book.getAlt_title());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
}
多个参数在URL问号之后,且个数不确定
@GET("News")
Call<NewsBean> getItem(@QueryMap Map<String, String> map);
更多用法参考
官方教程
你真的会用Retrofit2吗?Retrofit2完全教程 - 简书
Android】Retrofit网络请求参数注解,@Path、@Query、@QueryMa...
[用 Retrofit 2 简化 HTTP 请求(]https://www.jianshu.com/p/ebd1b37167e9)