文章来自于
准备工作
1 | //retrofit2.0 |
定义接口
在官方文档中,第一句话就是”Retrofit turns your HTTP API into a Java Interface”
我们的项目调用的接口来自于Gank的接口,例如:http://gank.io/api/data/Android/10/1
返回的Json数据:
定义一个接口类
1 | public interface GankApi { |
分析接口的定义
http://gank.io/api/data/Android/10/1
在这里我们将接口分为两部分baseUrl
和接口定义
,在上面的接口定义中,使用GET请求,直接请求了api/data/Android/10/1
,这样我们就能和后面定义的baseUrl
拼接成完整的接口了。
基本请求
官方文档中 The Retrofit class generates an implementation of the GithubService interface.
意思就是直接把Retrofit的接口变成一个类
创建一个Retrofit
1
2
3
4Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://gank.io")
.addConverterFactory(GsonConverterFactory.create())
.build();通过retrofit的create方法创建接口对象
1
GankApi api = retrofit.create(GankApi.class);
直接调用接口方法,返回一个Call
1
Call<GankBean> call = api.getAndroidInfo();
异步请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21call.enqueue(new Callback<GankBean>() {
@Override
public void onResponse(Call<GankBean> call, Response<GankBean> response) {
GankBean.ResultsBean bean = response.body().getResults().get(0);
mTextView.setText(
"_id:"+bean.get_id()+"\n"
+ "createdAt:" + bean.getCreatedAt() + "\n"
+ "desc:" + bean.getDesc() + "\n"
+ "images:" + bean.getImages() + "\n"
+ "publishedAt:" + bean.getPublishedAt() + "\n"
+ "source" + bean.getSource() + "\n"
+ "type:" + bean.getType() + "\n"
+ "url: " + bean.getUrl() + "\n"
+ "who:" + bean.getWho());
}
@Override
public void onFailure(Call<GankBean> call, Throwable t) {
}
});
运行结果
基本请求就是这样,配置做好,根据api定义好接口,配合Gson。请求完了就可以直接获得值了。
Get的动态参数
举个栗子
我们都知道url大多数都是拼接的,像我们查询天气的接口,就是动态传一个城市的名字。
http://op.juhe.cn/onebox/weather/query?cityname=深圳&key=您申请的KEY
默认cityname是深圳,后面就是我们需要拼接的
- WeatherApi
1
2
3
4public interface WeatherApi {
@GET("onebox/weather/query?cityname=深圳")
Call<WeatherDataBean> getWeather(@Query("key")String kry);
}
这里可以看到,在Get的时候还是把连接的后半段传进去,但是在这里最后拼接的时候是一个key,所以在传入参数的前面加上Query
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21// WeatherDataApi
// Get的动态参数
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://op.juhe.cn/")
.addConverterFactory(GsonConverterFactory.create())
.build();
WeatherApi api = retrofit.create(WeatherApi.class);
Call<WeatherDataBean> call = api.getWeather("4ea58de8a7573377cec0046f5e2469d5");
// 异步
call.enqueue(new Callback<WeatherDataBean>() {
@Override
public void onResponse(Call<WeatherDataBean> call, Response<WeatherDataBean> response) {
String info = response.body().getResult().getData().getRealtime().getWeather().getInfo();
mTextView.setText("深圳天气: " + info);
}
@Override
public void onFailure(Call<WeatherDataBean> call, Throwable t) {
}
});运行结果
Get参数请求
举个栗子
例如我们的接口是直接传参的
//后面三个参数
Android可接受参数 | Android | iOS | 休息视频 | 福利 | 前端 | App
count 最大 50
page 是页数
这种类型又该如何操作呢?
- 假设我们直接传入的参数是page
1
2
3
4public interface Gank2Api {
@GET("api/data/Android/10/{page}")
Call<GankBean> getAndroidInfo(@Path("page") int page);
}
在这里使用大括号做占位符,然后使用Path关键字,接着继续写代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// Get参数请求
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://gank.io/")
.addConverterFactory(GsonConverterFactory.create())
.build();
Gank2Api api = retrofit.create(Gank2Api.class);
api.getAndroidInfo(1).enqueue(new Callback<GankBean>() {
@Override
public void onResponse(Call<GankBean> call, Response<GankBean> response) {
mTextView.setText(response.body().getResults().get(0).getDesc());
}
@Override
public void onFailure(Call<GankBean> call, Throwable t) {
}
});
运行结果
Get参数拼接
1 | public interface WeatherApi2 { |
Get后面传入的参数并没有像cityname一类的参数,但是有一个QueryMap,传入的是键值对1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// Get参数拼接
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://op.juhe.cn/")
.addConverterFactory(GsonConverterFactory.create())
.build();
WeatherApi2 api = retrofit.create(WeatherApi2.class);
Map<String, String> params = new HashMap<>();
params.put("cityname","深圳");
params.put("key","4ea58de8a7573377cec0046f5e2469d5");
api.getWeather(params).enqueue(new Callback<WeatherDataBean>() {
@Override
public void onResponse(Call<WeatherDataBean> call, Response<WeatherDataBean> response) {
mTextView.setText(response.body().getResult().getData().getRealtime().getWeather().getInfo());
}
@Override
public void onFailure(Call<WeatherDataBean> call, Throwable t) {
}
});
运行结果
Post
1 | import retrofit2.Call; |
这里POST的地址和之前的get也是一样的,这里返回一个Result是我们自己定义的结果类,Body是表示参数,我需要一个User,那我们的User就是1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public class User {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
1 | public class Result { |
调用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16User user = new User();
user.setId(1);
user.setName("lgl");
api.postUser(user).enqueue(new Callback<Result>() {
@Override
public void onResponse(Call<Result> call, Response<Result> response) {
if (response.body().getYes() == 0) {
Toast.makeText(MainActivity.this, "成功", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<Result> call, Throwable t) {
}
});
我在这里传了一个user进去,细节不过就是id和name,如果请求成功,那就返回0,失败就是1,这里服务端定义,这样我们就POST完成了
Post提交表单
1 | @POST("user/edit") |
直接调用方法1
2
3
4
5
6
7
8
9
10
11
12
13api.editUser(1, "liuguilin").enqueue(new Callback<Result>() {
public void onResponse(Call<Result> call, Response<Result> response) {
if (response.body().getYes() == 0) {
Toast.makeText(MainActivity.this, "成功", Toast.LENGTH_SHORT).show();
}
}
public void onFailure(Call<Result> call, Throwable t) {
}
});
RxJava + Retrofit2.0
举个栗子
登录,登录成功后获取到user_id,再去请求用户信息,这里应该是两个请求对吧,我们先去写好接口,这里我们先用常规的方法去获取:1
2
3
4
5@POST("user/login")
Call<User> login(@Field("username") String user, @Field("password") String password);
@GET("user/info")
Call<User> getUser(@Query("id") String id);
这里的两个接口,一个是登录,传参用户名和密码,还有一个是用id去查找用户信息的1
2
3
4
5
6Retrofit retrofit = new Retrofit.Builder()
.baseUrl("baseUrl")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
api = retrofit.create(PostApi.class);
这里我们需要增加addCallAdapterFactory为我们后面的Rx做准备,然后我们调用两次1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28api.login("liuguilin", "748778890").enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
if (response.isSuccessful()) {
String id = response.body().getUser_id();
api.getUser(id).enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
Toast.makeText(MainActivity.this, "id:" +
response.body().getId()
+ "name:" + response.body().getName(),
Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(Call<User> call, Throwable t) {
}
});
}
}
@Override
public void onFailure(Call<User> call, Throwable t) {
}
});
RxJava写法
重新定义两个接口1
2
3
4
5@POST("user/login")
rx.Observable<User> loginForRX(@Body User user);
@GET("user/info")
rx.Observable<User> getUserForRX(@Query("id") String id);
这里的是伪代码,注意看使用方法1
2
3
4
5
6
7
8
9
10
11api.loginForRX(new User("liuguilin", "748778890")).flatMap(new Func1<User, Observable<User>>() {
public Observable<User> call(User user) {
return api.getUser(user.getUser_id());
}
}).subscribe(new Action1<User>() {
public void call(User user) {
Toast.makeText(MainActivity.this, "name:" + user.getName(), Toast.LENGTH_SHORT).show();
}
});