本人近期在看网络请求框架封装时,看到网上呼声最高的是此类,轻便又简洁,近日闲来无事,就为各位农友写了个案例,抠脚来的不喜勿喷哦。
OKhttp 相信各位农友都比较熟悉,它是一款高效的HTTP客户端,支持连接同一地址的链接共享同一个socket,通过连接池来减小响应延迟,还有透明的GZIP压缩,请求缓存等优势 Okhttp官网
Okhttp的配置
这里我是使用的gson作为ConverterFactory,你也可以使用其他的,并且自己写一个类实现下factory,我并没有这样操作。在这里提醒下,有些后台返回的数据格式并不是json格式,而是string格式,这里我介绍下对string格式返回值的支持 scalars,下面会见到配置
//okhttp的包
compile 'com.squareup.okhttp3:okhttp:3.9.0'
//retrofit对gson的支持
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
//请求字符串
compile 'com.squareup.retrofit2:converter-scalars:2.0.0'
创建一个对网络的管理类HttpManager,里面可以封装网络请求的baseurl,以及对okhttp的初始化
不同需求的okhttpclient可以多封装几个方法('详细代码后面会贴出')
'private OkHttpClient.Builder initOkhttpClien(){
//日志显示级别
OkHttpClient.Builder httpclient=new OkHttpClient().newBuilder();
httpclient.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
//添加 token 过期拦截,和日志打印,这里我写了个拦截器,这里可以对token刷新进行一些操作,具体看业务需要
httpclient.addInterceptor(new TokenInterceptor());
return httpclient;
}'
详细的okhttp使用以及源码讲解可以跳转Okhttp详解
ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。实时数据处理是一件普通的现象,有一个高效、干净和可扩展的方式来处理这些情景是重要的。使用 Observables 和 Operators 来熟练操作它们。ReactiveX 提供一个可组合又灵活的 API 来创建和处理数据流,同时简化了异步编程带来的一些担忧,如:线程创建和并发问题。
简单点来说:就是一个观察者通过订阅被观察者,依据被观察者的一些变化做出相应的动作,观察者可以改变被观察者的生活状态
- RxJava2的配置
这里我使用的是rxjava2,所以导入的包也是对应rxjava2的
compile 'io.reactivex.rxjava2:rxjava:2.0.1'
适配器 在前面加了,这里就不重复了
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
这里我写一个简单的例子:有三个学生,他们每个人有多种课程,我想打印每一个人的课程名都有哪些
**这里是为了演示使用,例子并没有实际意义**
public void testRx(){
List list=new ArrayList<>();
Student student=new Student();
List scos=new ArrayList<>();
for (int i = 0; i < 5; i++) {
Scort sc=new Scort();
sc.setName("name1"+i);
scos.add(sc);
}
student.setName("zhs1");
student.setScorts(scos);
Student student2=new Student();
List scos2=new ArrayList<>();
for (int j = 0; j < 5; j++) {
Scort sc=new Scort();
sc.setName("name2"+j);
scos2.add(sc);
}
student2.setName("zhs2");
student2.setScorts(scos2);
Student student3=new Student();
List scos3=new ArrayList<>();
for (int h = 0; h < 5; h++) {
Scort sc=new Scort();
sc.setName("name"+h);
scos3.add(sc);
}
student3.setName("zhs3");
student3.setScorts(scos3);
list.add(student);
list.add(student2);
list.add(student3);
Consumer与1.0的与Action1类似
Consumer consumer=new Consumer() {
@Override
public void accept(Scort scort) throws Exception {
System.out.println("课程名 "+scort.getName());
}
};
//背压的封装,具体可以看2.0介绍
//不需要for循环get等一堆操作既可以打印,简介明了
Flowable.fromIterable(list).flatMap(new Function>() {
@Override
public Publisher apply(Student student) throws Exception {
return Flowable.fromIterable(student.getScorts());
}
}).subscribe(consumer);
}
代码中Rxjava的体现在于 BaseObserver以及RxSchedulers;
后面会见到他们的使用
一个是对Observer的封装,一个是对全局的请求拦截的配置;
如果你不知道Observer是干什么的,建议去看看Rxjava的介绍
public abstract class BaseObserver<T> implements Observer<BaseBean<T>> {
private Context mContext;
private ProgressDialog progressDialog;
private Disposable disposable;
//默认无效果的请求
protected BaseObserver(Context context){
this.mContext=context.getApplicationContext();
}
//带进度条的请求
protected BaseObserver(Context context,boolean showProgress){
this.mContext=context.getApplicationContext();
if(showProgress){
progressDialog=new ProgressDialog(context);
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
disposable.dispose();
}
});
}
}
@Override
public void onSubscribe(Disposable d) {
disposable=d;
}
@Override
public void onNext(BaseBean value) {
//这里对数据bean的封装,这里看个人的网络回掉的结果来操作,我是随便写的
if (value.getTotal()>0) {
T t = value.getSubject();
onHandleSuccess(t);
} else {
onHandleError(value.getTitle());
}
}
@Override
public void onError(Throwable e) {
if(progressDialog!=null){
progressDialog.dismiss();
}
}
@Override
public void onComplete() {
if(progressDialog!=null&&progressDialog.isShowing()){
progressDialog.dismiss();
}
}
protected abstract void onHandleSuccess(T t);
protected void onHandleError(String msg) {
Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
}
}
/**
* 设置同一的拦截,对每个订阅做相同的标准
*/
public class RxSchedulers {
public static <T> ObservableTransformer<T, T> compose(final Context context) {
return new ObservableTransformer<T, T>() {
@Override
public ObservableSource<T> apply(Observable observable) {
return observable
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.doOnSubscribe(new Consumer() {
@Override
public void accept(Disposable disposable) throws Exception {
if(!NetUtils.isNetworkConnected(context)){
Toast.makeText(context,"网络异常",Toast.LENGTH_SHORT).show();
}
}
})
.observeOn(AndroidSchedulers.mainThread());
}
};
}
}
也可以换一种写法(看个人喜好)
public class BaseObservableTransFormer<T> implements ObservableTransformer<T,T>{
private Context context;
public BaseObservableTransFormer(Context context){
this.context=context;
}
@Override
public ObservableSource<T> apply(Observable upstream) {
return upstream.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.doOnSubscribe(new Consumer() {
@Override
public void accept(Disposable disposable) throws Exception {
//判断网络
if(!NetUtils.isNetworkConnected(context)){
Toast.makeText(context,"网络异常",Toast.LENGTH_SHORT).show();
}
}
})
.observeOn(AndroidSchedulers.mainThread());
}
}
推荐一个Rxjava的入门简介Rxjava简介
简单的说Retrofit将访问方式分成了三步,1.request的type设置;2.参数的配置,3.对response的回掉处理;
其实volley也是这样,只不过retrofit将更多的事情放到了对callback的处理,所以让他做到了像一个方法请求了api似S的效果;
Retrofit的配置
这里我使用的是rxjava2,所以导入的包也是对应rxjava2的,如果你还是使用rxjava1,可以设置rxjava1的包,此包对1也兼容
//retrofit的包
compile 'com.squareup.retrofit2:retrofit:2.3.0'
//对gson的支持
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
//对rxjava的适配
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
1.创建一个请求的接口类
//此处封装的是Observable,Rxjava中的被观察者
public interface ApiRequest {
@GET("top250")
Observable>> getMovie(@Query("start") int start, @Query("count") int count);
//这个BaseBean是我对数据的封装,像后台返回给我们的数据都是具有一定的格式,我们以此可以做一些操作
...类似更多的接口都卸载这个类中
}
2.配置Retrofit的全局使用
//同样,我们在配置okhttp的HttpManager类中初始化这个配置,这里使用简单的单例模式
SingleHolder写在HttpManager类中
private static class SingleHolder{
private static HttpManager httpManager=null;
public static HttpManager getInstance(Context context){
if(httpManager==null){
httpManager=new HttpManager(context);
}
return httpManager;
}
}
//对Retrofit的初始化
private HttpManager(Context context){
this.mContext=context;
retrofit=new Retrofit.Builder()
//对okgttp的初始化
.client(initOkhttpClien().build())
//基础的网络请求域名
.baseUrl(baseUrl)
//对返回字符串的支持,注意这个要写在gson之前
.addConverterFactory(ScalarsConverterFactory.create())
//对gson的支持
.addConverterFactory( GsonConverterFactory.create())
//对rxjava的支持
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
//接口方法类的反射获取
request = retrofit.create(ApiRequest.class);
}
//简单的单例模式
public static HttpManager init(Context context){
return SingleHolder.getInstance(context);
}
3.使用rxjava来返回响应体
//这个方法也是写在HttpManager中,对应的在ApiRequest 写一个方法,这里就写一个
public void getMovie(int strat, int count, BaseObserver> subscriber)
{
request.getMovie(strat,count).compose(RxSchedulers.>>compose(mContext)) .subscribe( subscriber);
}
4.在代码中的使用
HttpManager.init(this).getMovie(0, 10, new BaseObserver>(this) {
//对网络判断的封装放在RxSchedulers中,对返回值code判断放在BaseObserver中
@Override
protected void onHandleSuccess(List subjects) {
System.out.println(subjects.get(2).toString());
}
})
;
项目地址 https://gitee.com/nimodou/RetrofitRxjava.git