首先,先给出官网:
GitHub-Retrofit
官网-Retrofit
其次,要吐槽一下官网首页给出的例子。如果你照着例子改,会发现根本没法运行,不是少包就是少关键语句。
相关内容可以参看我的另一篇文章:Retrofit(2.0)入门小错误 – Could not locate ResponseBody xxx Tried: * retrofit.BuiltInConverters
无论如何咱们还是先跑起来一个小栗子吧。
首先,在gralde文件中引入后续要用到的库。
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2'
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'io.reactivex:rxjava:1.0.14'
compile 'io.reactivex:rxandroid:1.0.1'
接下来跟着我一步两步往下走。
创建服务类和Bean
public static class Contributor {
public final String login;
public final int contributions;
public Contributor(String login, int contributions) {
this.login = login;
this.contributions = contributions;
}
@Override
public String toString() {
return "Contributor{" +
"login='" + login + '\'' +
", contributions=" + contributions +
'}';
}
}
public interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Call> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
接下来创建Retrofit2的实例,并设置BaseUrl和Gson转换。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.client(new OkHttpClient())
.build();
创建请求服务,并为网络请求方法设置参数
GitHub gitHubService = retrofit.create(GitHub.class);
Call> call = gitHubService.contributors("square", "retrofit");
最后,请求网络,并获取响应
try{
Response> response = call.execute(); // 同步
Log.d(TAG, "response:" + response.body().toString());
} catch (IOException e) {
e.printStackTrace();
}
通过调用Retrofit2的execute(同步)或者enqueue(异步)方法,发送请求到网络服务器,并返回一个响应(Response)。
由于call只能被执行一次,所以按照上面的顺序执行会得到如下错误。
java.lang.IllegalStateException: Already executed
我们可以通过clone,来克隆一份call,从新调用。
// clone
Call> call1 = call.clone();
// 5. 请求网络,异步
call1.enqueue(new Callback>() {
@Override
public void onResponse(Response> response, Retrofit retrofit) {
Log.d(TAG, "response:" + response.body().toString());
}
@Override
public void onFailure(Throwable t) {
}
});
网络访问肯定要涉及到参数请求,Retrofit为我们提供了各式各样的组合方法。下面以标题+小例子的方式给出讲解。
// 服务
interface SomeService {
@GET("/some/endpoint?fixed=query")
Call someEndpoint();
}
// 方法调用
someService.someEndpoint();
// 请求头
// GET /some/endpoint?fixed=query HTTP/1.1
// 服务
interface SomeService {
@GET("/some/endpoint")
Call someEndpoint(
@Query("dynamic") String dynamic);
}
// 方法调用
someService.someEndpoint("query");
// 请求头
// GET /some/endpoint?dynamic=query HTTP/1.1
// 服务
interface SomeService {
@GET("/some/endpoint")
Call someEndpoint(
@QueryMap Map dynamic);
}
// 方法调用
someService.someEndpoint(
Collections.singletonMap("dynamic", "query"));
// 请求头
// GET /some/endpoint?dynamic=query HTTP/1.1
interface SomeService {
@GET("/some/endpoint")
Call someEndpoint(
@Query("dynamic") String dynamic);
}
// 方法调用
someService.someEndpoint(null);
// 请求头
// GET /some/endpoint HTTP/1.1
interface SomeService {
@GET("/some/endpoint?fixed=query")
Call someEndpoint(
@Query("dynamic") String dynamic);
}
// 方法调用
someService.someEndpoint("query");
// 请求头
// GET /some/endpoint?fixed=query&dynamic=query HTTP/1.1
interface SomeService {
@GET("/some/endpoint/{thing}")
Call someEndpoint(
@Path("thing") String thing);
}
someService.someEndpoint("bar");
// GET /some/endpoint/bar HTTP/1.1
interface SomeService {
@GET("/some/endpoint")
@Headers("Accept-Encoding: application/json")
Call someEndpoint();
}
someService.someEndpoint();
// GET /some/endpoint HTTP/1.1
// Accept-Encoding: application/json
interface SomeService {
@GET("/some/endpoint")
Call someEndpoint(
@Header("Location") String location);
}
someService.someEndpoint("Droidcon NYC 2015");
// GET /some/endpoint HTTP/1.1
// Location: Droidcon NYC 2015
interface SomeService {
@GET("/some/endpoint")
@Headers("Accept-Encoding: application/json")
Call someEndpoint(
@Header("Location") String location);
}
someService.someEndpoint("Droidcon NYC 2015");
// GET /some/endpoint HTTP/1.1
// Accept-Encoding: application/json
// Location: Droidcon NYC 2015
interface SomeService {
@POST("/some/endpoint")
Call someEndpoint();
}
someService.someEndpoint();
// POST /some/endpoint?fixed=query HTTP/1.1
// Content-Length: 0
interface SomeService {
@POST("/some/endpoint")
Call someEndpoint(
@Body SomeRequest body);
}
someService.someEndpoint();
// POST /some/endpoint HTTP/1.1
// Content-Length: 3
// Content-Type: greeting
//
// Hi!
interface SomeService {
@FormUrlEncoded
@POST("/some/endpoint")
Call someEndpoint(
@Field("name1") String name1,
@Field("name2") String name2);
}
someService.someEndpoint("value1", "value2");
// POST /some/endpoint HTTP/1.1
// Content-Length: 25
// Content-Type: application/x-www-form-urlencoded
//
// name1=value1&name2=value2
interface SomeService {
@FormUrlEncoded
@POST("/some/endpoint")
Call someEndpoint(
@FieldMap Map names);
}
someService.someEndpoint(
// ImmutableMap是OKHttp中的工具类
ImmutableMap.of("name1", "value1", "name2", "value2"));
// POST /some/endpoint HTTP/1.1
// Content-Length: 25
// Content-Type: application/x-www-form-urlencoded
//
// name1=value1&name2=value2
interface GitHubService {
@GET("/repos/{owner}/{repo}/contributors")
Call> repoContributors(
@Path("owner") String owner,
@Path("repo") String repo);
@GET
Call> repoContributorsPaginate(
@Url String url);
}
// 调用
Call> call = gitHubService.repoContributors("square", "retrofit");
Response> response = call.execute();
// 响应结果
// HTTP/1.1 200 OK
// Link:
page=2>; rel="next", //api.github.com/repositories/892275/
contributors?page=3>; rel="last"
// 获取到头中的数据
String links = response.headers().get("Link");
String nextLink = nextFromGitHubLinks(links);
// https://api.github.com/repositories/892275/contributors?page=2
interface GitHubService {
@GET("/repos/{owner}/{repo}/contributors")
// Call 代表的是CallBack回调机制
Call> repoContributors(
@Path("owner") String owner,
@Path("repo") String repo);
@GET("/repos/{owner}/{repo}/contributors")
// Observable 代表的是RxJava的执行
Observable> repoContributors2(
@Path("owner") String owner,
@Path("repo") String repo);
@GET("/repos/{owner}/{repo}/contributors")
Future> repoContributors3(
@Path("owner") String owner,
@Path("repo") String repo);
}
注意,要在构建Retrofit时指定适配器模式为RxJavaCallAdapterFactory
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl("http://www.duitang.com")
.build();
否则,会报出如下错误:
Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for rx.Observable. Tried:
* retrofit.ExecutorCallAdapterFactory
授人以鱼不如授人以渔 这是出自官方开发人员的讲解的网站(自备梯子)
Retrofit作为一个上层框架,自然有很多底层lib库支持,okio
和okhttp
都包含其中。
这是一些关于OK
库的讲解