简介
Retrofit是一个网络请求框架,是对okhttp的进一步封装,支持同步和异步、支持多种数据的解析(默认使用Gson),也支持RxJava。 官网地址 github地址
使用步骤
1、添加依赖与权限
1.1在build.gradle(:app)添加Retrofit库依赖

implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
导入的这两个包,第一个是retrofit的本体,第二个是gson的转换器(转换器有很多种)
1.2在AndroidManifest.xml添加网络权限

<!-- 联网 -->
<uses-permission android:name="android.permission.INTERNET" />
如果没添加去请求网络就会报错E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher 
2、创建Retrofit请求基础配置
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
上面代码构造了一个Retrofit对象,值得注意的是baseUrl不能为空,且最好以 / 斜杠结尾,这样后面第4步创建网络请求接口的时候,就不用写 / 斜杠了 每次要去请求的时候,都要创建一个Retrofit,那其实可以封装一下这段代码
public class ApiServiceManager {
private Retrofit mRetrofit;
private static ApiServiceManager mInstance;
public static ApiServiceManager get() {
return mInstance = new ApiServiceManager();
}
private ApiServiceManager() {
mRetrofit = new Retrofit.Builder()
.baseUrl(UrlConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
public <T> T create(final Class<T> service) {
return mRetrofit.create(service);
}
}
里面的UrlConfig.BASE_URL也是我把地址单独放起来了
public class UrlConfig {
private UrlConfig() {
}
@Keep
private static class BaseUrls {
@Keep
private static final String Github = "https://api.github.com/";
@Keep
private static final String QQ = "https://api.uomg.com/";
}
public static final String BASE_URL = BaseUrls.Github;
}
其实呢在网络请求的时候,最首要的,就是要确定我们需要访问的网络路径 本文有两个案例,一个是获取Github用户数据,一个是获取QQ用户数据 获取Github用户数据的路径:https://api.github.com/users/hongyangAndroid 点此访问 其中 https://api.github.com/ 可以当作共用的接口地址先存起来,如上面代码的Github,后文获取Github用户数据的时候就用这个地址,后面的地址可以在第4步创建网络请求接口的时候把剩下的写了 hongyangAndroid 可以换成需要访问的Github(这里借用一下hongyang大神的) 获取QQ用户数据的路径:https://api.uomg.com/api/qq.info?qq=774740085 点此访问 https://api.uomg.com/ 后文获取QQ用户数据的时候就用这个地址 其中774740085 可以换成需要访问的QQ 这里使用的是免费的API接口 知道了需要访问的网络路径以后,可以先在浏览器访问看看,这样可以确定接口返回数据的结构,以此来编写数据返回后的Bean类(步骤3) 这是访问的Github的  这是访问的QQ的 
3、创建数据返回后的Bean类
因为要讲解两个案例,所以新建了两个Bean类 根据上文访问接口,看见了返回的数据,所以编写数据类如下
public class GithubBean {
public String login;
}
public class QqBean {
public String name = "";
}
其实还可以这样写
public class GithubBean {
private String login;
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
}
通过get()和set()方法更安全
4、创建网络请求的接口
先展示一下代码
public interface ApiService {
@GET("users/{user}")
Call<GithubBean> getGithubData(@Path("user") String user);
@GET("api/qq.info")
Call<QqBean> getQqData(@Query("qq") String qq);
}
网络请求接口要根据网络请求地址来创建,要严格和后台对上,不能多符号啊空格什么的。 这一步其实就是把API接口地址转化成一个Java接口,其实Retrofit就是通过注解将HTTP转化为Java接口。 在上面代码中出现的@GET 、@Path 、@Query 就是注释,下面先来了解一下这些注释吧 网络请求方法类注解 HTTP请求主要分为Get和Post两种方法。 @GET就是采用Get方法发送网络请求 @POST就是采用Post方法发送网络请求 当然还有比如==@HEAD==等,不常用,本文就不介绍了 网络请求参数类注解(只介绍一些,其他的可以百度都有) 比如上面的代码中的@GET("users/{user}") 和@GET("api/qq.info") 就都是使用Get请求方式 那Get请求方式是把参数是放在路径当中的 比如获取Github用户数据的路径:https://api.github.com/users/hongyangAndroid 获取QQ用户数据的路径:https://api.uomg.com/api/qq.info?qq=774740085 最后面跟着的,就是请求参数 那么怎么拼接请求参数到路径里面呢? @Path用于URL地址的缺省值 代码:
@GET("users/{user}")
Call<GithubBean> getGithubData(@Path("user") String user);
在访问Github用户数据的路径:https://api.github.com/users/hongyangAndroid的时候 因为前面写了BASE_URL,所以一起拼接起来的路径是https://api.github.com/users/{user} 里面的{user}会被替换为getGithubData()方法的第一个参数user @Query用于@GET方法的查询参数(Query可以等于Url的?后面的key-value,就很像占位符那样) 比如获取QQ用户数据的路径:https://api.uomg.com/api/qq.info?qq=774740085里面的 ?qq=774740085 就可以用==@Query== 代码:
@GET("api/qq.info")
Call<QqBean> getQqData(@Query("qq") String qq);
Post的请求是把参数放在请求体当中,所以需要用到==@Body== 获取随机土味情话的路径:https://api.uomg.com/api/rand.qinghua
@POST("api/rand.qinghua")
Call<QhBean> getQhData(@Body RequestBody requestBody);
@Body一般有4个种类,这里讲解自定义创建的 首先,在接口处设置@Body RequestBody requestBody 其次,需要手动解析Response请求返回 有时候我们不需要使用GsonConverterFactory帮我们解析Body数据,我们希望自己能操作数据并且解析。比如获取下载数据的流,我们需要使用ResponseBody类(这个类是OkHttp返回Body类)。
public class RequestBean<T> {
private static final String ACTION_MEDIATYPE = "application/json; charset=utf-8";
public T data;
public RequestBody createRequestBody() {
return RequestBody.create(MediaType.parse(ACTION_MEDIATYPE), JSON.toJSONString(this));
}
public static RequestBody createDefaultRequestBody() {
return RequestBody.create(MediaType.parse(ACTION_MEDIATYPE), "{}");
}
public static RequestBody createListRequestBody(List list) {
return RequestBody.create(MediaType.parse(ACTION_MEDIATYPE), JSON.toJSONString(list));
}
}
这里使用alibaba的fastjson解析数据,所以还需要添加依赖
implementation 'com.alibaba:fastjson:1.2.75'
请求头类注解、标记类注解(就先不介绍了,可以自行百度,以后说不定会在本文中更新的)
5、请求网络(异步、同步)
GET异步请求 请求Github用户数据
private void getGithubData() {
ApiService apiService = ApiServiceManager.get().create(ApiService.class);
Call<GithubBean> call = apiService.getGithubData("hongyangAndroid");
call.enqueue(new Callback<GithubBean>() {
@Override
public void onResponse(Call<GithubBean> call, Response<GithubBean> response) {
if (response.body() == null) {
mBinding.contentTv.setText("无数据");
return;
}
GithubBean githubBean = response.body();
mBinding.contentTv.setText(githubBean.login);
}
@Override
public void onFailure(Call<GithubBean> call, Throwable t) {
mBinding.contentTv.setText(t.getMessage());
}
});
}
运行展示:  获取QQ用户数据
private void getQqData() {
ApiService apiService = ApiServiceManager.get().create(ApiService.class);
Call<QqBean> call = apiService.getQqData("774740085");
call.enqueue(new Callback<QqBean>() {
@Override
public void onResponse(Call<QqBean> call, Response<QqBean> response) {
if (response.body() == null) {
mBinding.contentTv.setText("无数据");
return;
}
QqBean qqBean = response.body();
mBinding.contentTv.setText(qqBean.name);
}
@Override
public void onFailure(Call<QqBean> call, Throwable t) {
mBinding.contentTv.setText(t.getMessage());
}
});
}
运行展示:  GET同步请求
private void getQqDataSync() {
ApiService apiService = ApiServiceManager.get().create(ApiService.class);
Call<QqBean> call = apiService.getQqData("774740085");
new Thread(new Runnable() {
@Override
public void run() {
try {
Response<QqBean> response = call.execute();
if (response.body() == null) {
Log.e("TAG", "无数据");
return;
}
QqBean qqBean = response.body();
Log.e("TAG", "name=" + qqBean.name);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
注意Android主线程不能操作网络请求。 运行结果  POST异步请求
private void getQhData() {
ApiService apiService = ApiServiceManager.get().create(ApiService.class);
Call<QhBean> call = apiService.getQhData(RequestBean.createDefaultRequestBody());
call.enqueue(new Callback<QhBean>() {
@Override
public void onResponse(Call<QhBean> call, Response<QhBean> response) {
if (response.body() == null) {
mBinding.contentTv.setText("无数据");
return;
}
QhBean qhBean = response.body();
mBinding.contentTv.setText(qhBean.content);
}
@Override
public void onFailure(Call<QhBean> call, Throwable t) {
mBinding.contentTv.setText(t.getMessage());
}
});
}

拓展
Retrofit是基于Okhttp开发的网络请求框架,所以有一部分如请求超时时间、拦截器、代理等功能依然需要使用Okhttp的方式来配置,那么如何配置呢?
public class ApiServiceManager {
public static final String TAG = "resultValue";
private Retrofit mRetrofit;
private static ApiServiceManager mInstance;
public static ApiServiceManager get() {
return mInstance = new ApiServiceManager();
}
private ApiServiceManager() {
mRetrofit = new Retrofit.Builder()
.baseUrl(UrlConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(getOkHttpClient())
.build();
}
private OkHttpClient getOkHttpClient() {
return new OkHttpClient.Builder()
.connectTimeout(100, TimeUnit.SECONDS)
.writeTimeout(100, TimeUnit.SECONDS)
.readTimeout(100, TimeUnit.SECONDS)
.build();
}
public <T> T create(final Class<T> service) {
return mRetrofit.create(service);
}
}
Retrofit和RxJava的结合可以参考本人的另一篇文章
|