Android Retrofit网络请求框架
简介
Retrofit是一个网络请求框架,是对okhttp的进一步封装,支持同步和异步、支持多种数据的解析(默认使用Gson),也支持RxJava。
官网地址
github地址
使用步骤
1、添加依赖与权限
1.1在build.gradle(:app)添加Retrofit库依赖
//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 retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")//设置网络请求的Url地址
.addConverterFactory(GsonConverterFactory.create())//设置数据解析器(Gson转换器)
.build();
上面代码构造了一个Retrofit对象,值得注意的是baseUrl不能为空,且最好以 / 斜杠结尾,这样后面第4步创建网络请求接口的时候,就不用每次在每个网络请求接口里都写 / 斜杠了
Retrofit把网络请求的URL分成了两部分,前半部分放在Retrofit对象里(一般一个项目的前半部分都是一样的),后半部分放在网络请求接口里(就比如放在@GET的注解里面,但是如果网络请求接口里的URL是一个完整的网址,那么Retrofit对象里的URL可以不写)
每次要去请求的时候,都要创建一个Retrofit,那其实可以封装一下这段代码
/**
* 接口管理器
*/
public class ApiServiceManager {
private Retrofit mRetrofit;
private static ApiServiceManager mInstance = new ApiServiceManager();
public static ApiServiceManager get() {
return mInstance;
}
private ApiServiceManager() {
//创建Retrofit实例
mRetrofit = new Retrofit.Builder()
.baseUrl(UrlConfig.BASE_URL) //设置网络请求的Url地址
.addConverterFactory(GsonConverterFactory.create()) //设置数据解析器(支持Gson解析转换器)
.build();
}
/**
* 创建对应的ApiService
*
* @param service 接口类
*/
public <T> T create(final Class<T> service) {
return mRetrofit.create(service);
}
/** 获取Retrofit对象 */
public Retrofit getRetrofit() {
return mRetrofit;
}
}
里面的UrlConfig.BASE_URL也是我把地址单独放起来了
/**
* 地址配置
*/
public class UrlConfig {
private UrlConfig() {
}
/**
* 接口路径
*/
@Keep
private static class BaseUrls {
/**
* Github地址
*/
@Keep
private static final String Github = "https://api.github.com/";
/**
* 获取QQ的地址
*/
@Keep
private static final String UOMG = "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类
根据上文访问接口,看见了返回的数据,所以编写数据类如下
/**
* Github数据类
*/
public class GithubBean {
/**
* 登录名字
*/
public String login;
}
/**
* QQ数据类
*/
public class QqBean {
/**
* QQ名字
*/
public String name = "";
}
其实还可以这样写
/**
* Github数据类
*/
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 {
//获取Github用户数据
@GET("users/{user}")//@GET注解的作用:采用Get方法发送网络请求,请求的地址为:BASE_URL+"users/{user}"
Call<GithubBean> getGithubData(@Path("user") String user);//getGithubData()接收网络请求数据的方法
//返回类型为Call<*>,*是接收数据的类(即GithubBean类)
//获取QQ用户数据
@GET("api/qq.info")
Call<QqBean> getQqData(@Query("qq") String qq);
}
网络请求接口要根据网络请求地址来创建,要严格和后台对上,不能多符号啊空格什么的。
@GET
注解里传入的就是网络请求的部分URL地址(如步骤2所说),这地址的前半部分在Retrofit对象
这一步其实就是把API接口地址转化成一个Java接口,其实Retrofit就是通过注解将HTTP转化为Java接口。
在上面代码中出现的@GET
、@Path
、@Query
就是注释,下面先来了解一下这些注释吧
网络请求方法类注解
HTTP请求主要分为Get和Post两种方法。
@GET就是采用Get方法发送网络请求
@POST就是采用Post方法发送网络请求
当然还有比如==@HEAD==等,不常用,本文就不介绍了
网络请求参数类注解(本文只介绍@GET,其他的可以百度都有)
比如上面的代码中的@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);
请求头类注解、标记类注解(就先不介绍了,可以自行百度,以后说不定会在本文中更新的)
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主线程不能操作网络请求。
运行结果
拓展
Retrofit是基于Okhttp开发的网络请求框架,所以有一部分如请求超时时间、拦截器、代理等功能依然需要使用Okhttp的方式来配置,那么如何配置呢?
在ApiServiceManager里添加一下就可以啦
/**
* 接口管理器
*/
public class ApiServiceManager {
private ApiServiceManager() {
//创建Retrofit实例
mRetrofit = new Retrofit.Builder()
.baseUrl(UrlConfig.BASE_URL) //设置网络请求的Url地址
.addConverterFactory(GsonConverterFactory.create()) //设置数据解析器(支持Gson解析转换器)
.client(getOkHttpClient())//OkHttpClient
.build();
}
/**
* 获取一个OkHttpClient
*/
private OkHttpClient getOkHttpClient() {
return new OkHttpClient.Builder()
.connectTimeout(100, TimeUnit.SECONDS)//连接超时
.writeTimeout(100, TimeUnit.SECONDS)//读取超时
.readTimeout(100, TimeUnit.SECONDS)//写入超时
.build();
}
}
Retrofit和RxJava的结合可以参考本人的另一篇文章