Retrofit基本使用
内容
- 基础
- 接口配置
- 发送请求
- 异步请求 && 示例一
- Convert && 示例二
- RxJava支持 && 示例三
- 参考:Retrofit官网
基础
使用Retrofit能够通过添加注解,轻松地将 HTTP API 转化为 Java 接口,示例如下:
compile 'com.squareup.okhttp3:okhttp:3.8.1'
compile 'com.squareup.retrofit2:retrofit:2.3.0'
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
使用上述接口:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
调用 call 的 execute 方法或者 enqueue 方法进行同步或者异步的网络请求:
Call<List<Repo>> repos = service.listRepos("octocat");
repos.execute() //同步调用
repos.enqueue(new Callback<T>() {...}) //异步调用
接口配置
- 使用 @GET, @POST, @PUT, @DELETE, @HEAD 注解来相应标注 HTTP API 的请求类型
- 使用@Path、@Query 注解标注 api url 中的参数
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
- 复杂结构的参数使用 @QueryMap 来标注
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
- 使用@Body注解 可以将 Java 对象标注为请求体
@POST("users/new")
Call<User> createUser(@Body User user);
- 其他注解:
- @FormUrlEncoded
- @Multipart
- @Headers
示例一
使用Gank.io的随机数据接口,实现如下简单的示例:
GankService.java
public interface GankService {
// http://gank.io/api/random/data/分类/个数
@GET("random/data/{category}/{number}")
Call<ResponseBody> getResponseData(@Path("category") String category, @Path("number") String number);
}
GankActivity.java
public class GankActivity extends AppCompatActivity {
TextView tvGank;
final String pageSize = "10";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gank);
findViewById(R.id.btn_gank).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getData();
}
});
tvGank = (TextView) findViewById(R.id.tv_gank);
}
private void getData() {
// BaseUrl 需要以 '/' (slash)结尾
final String baseUrl = "http://gank.io/api/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.build();
GankService service = retrofit.create(GankService.class);
Call<ResponseBody> call = service.getResponseData("Android", pageSize);
// call.execute(); // 同步调用
// call.enqueue(); // 异步调用
// call.cancel(); // 取消请求
// call.isCanceled(); // 是否请求
// call.isExecuted(); // 是否调用
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
try {
tvGank.setText(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d("corey", "call.enqueue failed:" + t.toString());
}
});
}
}
Converter
- 默认地,若不做 converter 相关配置,Retrofit只能将网络请求的 HTTP body 转化为 OkHttp 中的 ResponseBody 类型,@Body中接收参数也只能接收 ResponseBody 类型
- Retrofit 提供了多种解析库的converter,只需在build时添加配置即可使用,例如,要添加支持Gson解析库从而支持对Json的解析,只需如下:
compile 'com.google.code.gson:gson:2.8.1'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHubService service = retrofit.create(GitHubService.class);
- 除了Retrofit内置支持的各个解析库外,还可以添加自定义的解析库。新建一个类继承自 Converter.Factory ,然后在初始化Retrofit示例时,将该自定义的Converter传入即可。
示例二
GankService.java
public interface GankService {
// http://gank.io/api/random/data/分类/个数
@GET("random/data/{category}/{number}")
Call<GankRandom> getEntityData(@Path("category") String category, @Path("number") String number);
}
GankActivity2.java
public class GankActivity2 extends AppCompatActivity {
TextView tvGank;
RecyclerView rvGank;
SimpleStringAdapter simpleStringAdapter;
ProgressDialog progressDialog;
final String pageSize = "10";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gank2);
findViewById(R.id.btn_gank2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getData();
}
});
tvGank = (TextView) findViewById(R.id.tv_gank2);
rvGank = (RecyclerView) findViewById(R.id.rv_gank2);
rvGank.setLayoutManager(new LinearLayoutManager(this));
simpleStringAdapter = new SimpleStringAdapter(this);
rvGank.setAdapter(simpleStringAdapter);
progressDialog = new ProgressDialog(this);
}
private void getData() {
progressDialog.show();
final String baseUrl = "http://gank.io/api/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
GankService service = retrofit.create(GankService.class);
Call<GankRandom> call = service.getEntityData("Android", pageSize);
call.enqueue(new Callback<GankRandom>() {
@Override
public void onResponse(Call<GankRandom> call, Response<GankRandom> response) {
List<String> data = new ArrayList<String>();
for (GankRandom.ResultsBean bean : response.body().getResults()) {
data.add(bean.getDesc());
}
simpleStringAdapter.setStrings(data);
progressDialog.dismiss();
}
@Override
public void onFailure(Call<GankRandom> call, Throwable t) {
Log.d("corey", "call.enqueue failed:" + t.toString());
progressDialog.dismiss();
}
});
}
}
Retrofit + RxJava
- Retrofit可以配合RxJava使用,具体的使用如下:
- 定义接口时,将其返回值设为Observable
- 新建Retrofit实例时,添加RxJava支持
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.9'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
interface GitHubService {
@GET("users/{user}/repos")
Observable<List<Repo>> listRepos(@Path("user") String user);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
GitHubService service = retrofit.create(GitHubService.class);
service.listRepos("google")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<Repo>>(){...})
示例三
GankService.java
public interface GankService {
// http://gank.io/api/random/data/分类/个数
@GET("random/data/{category}/{number}")
Observable<GankRandom> getObservableData(@Path("category") String category, @Path("number") String number);
}
GankActivity3.java
public class GankActivity3 extends AppCompatActivity {
TextView tvGank;
RecyclerView rvGank;
SimpleStringAdapter simpleStringAdapter;
Disposable disposable;
ProgressDialog progressDialog;
final String pageSize = "10";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gank3);
findViewById(R.id.btn_gank3).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getData();
}
});
tvGank = (TextView) findViewById(R.id.tv_gank3);
rvGank = (RecyclerView) findViewById(R.id.rv_gank3);
rvGank.setLayoutManager(new LinearLayoutManager(this));
simpleStringAdapter = new SimpleStringAdapter(this);
rvGank.setAdapter(simpleStringAdapter);
progressDialog = new ProgressDialog(this);
}
private void getData() {
final String baseUrl = "http://gank.io/api/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
GankService service = retrofit.create(GankService.class);
disposable = service.getObservableData("Android", pageSize)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(new Function<GankRandom, List<String>>() {
@Override
public List<String> apply(@NonNull GankRandom gankRandom) throws Exception {
List<String> toReturn = new ArrayList<>();
for (GankRandom.ResultsBean gankBean : gankRandom.getResults()) {
toReturn.add(gankBean.getDesc());
}
return toReturn;
}
})
.subscribeWith(
new DisposableObserver<List<String>>() {
@Override
protected void onStart() {
progressDialog.show();
}
@Override
public void onNext(@NonNull List<String> titles) {
progressDialog.dismiss();
simpleStringAdapter.setStrings(titles);
}
@Override
public void onError(@NonNull Throwable e) {
progressDialog.dismiss();
}
@Override
public void onComplete() {
}
}
);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (!disposable.isDisposed()) {
disposable.dispose();
}
}
}