Rxjava+ReTrofit+okHttp深入浅出-终极封装

Rxjava+ReTrofit+okHttp深入浅出-终极封装

背景:

学习Rxjava和retrofit已经很长时间了,功能确实很强大,但是使用起来还是有点复杂,代码的重复性太高,所以决定把基于retrofit和rxjava的处理统一封装起来,实现的功能:

    1.Retrofit+Rxjava+okhttp基本使用方法
    2.统一处理请求数据格式
    3.统一的ProgressDialog和回调Subscriber处理
    4.取消http请求
    5.预处理http请求
    5.返回数据的统一判断

效果:

封装后http请求代码如下

 //    完美封装简化版
    private void simpleDo() {
        SubjectPost postEntity = new SubjectPost(new ProgressSubscriber(simpleOnNextListener, this), true);
        HttpManager manager = HttpManager.getInstance();
        manager.doHttpDeal(postEntity);
    }

    //   回调一一对应
    HttpOnNextListener simpleOnNextListener = new HttpOnNextListener<List<Subject>>() {
        @Override
        public void onNext(List<Subject> subjects) {
            tvMsg.setText("已封装:\n" + subjects.toString());
        }
    };>

是不是很简单?你可能说这还简单,好咱们对比一下正常使用retrofit的方法

 /**
     * Retrofit加入rxjava实现http请求
     */
    private void onButton9Click() {
        //手动创建一个OkHttpClient并设置超时时间
        okhttp3.OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(5, TimeUnit.SECONDS);

        Retrofit retrofit = new Retrofit.Builder()
                .client(builder.build())
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .baseUrl(HttpManager.BASE_URL)
                .build();

//        加载框
        final ProgressDialog pd = new ProgressDialog(this);

        HttpService apiService = retrofit.create(HttpService.class);
        Observable<RetrofitEntity> observable = apiService.getAllVedioBy(true);
        observable.subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        new Subscriber<RetrofitEntity>() {
                            @Override
                            public void onCompleted() {
                                if (pd != null && pd.isShowing()) {
                                    pd.dismiss();
                                }
                            }

                            @Override
                            public void onError(Throwable e) {
                                if (pd != null && pd.isShowing()) {
                                    pd.dismiss();
                                }
                            }

                            @Override
                            public void onNext(RetrofitEntity retrofitEntity) {
                                tvMsg.setText("无封装:\n" + retrofitEntity.getData().toString());
                            }

                            @Override
                            public void onStart() {
                                super.onStart();
                                pd.show();
                            }
                        }

                );
    }

可能你发现确是代码有点多,但是更加可怕的是,如果你一个activity或者fragment中多次需要http请求,你需要多次重复的写回调处理(一个回到就有4个方法呀!!!!反正我是忍受不了),而且以上处理还没有做过多的判断和错误校验就如此复杂!~好了介绍完了,开始咱们的优化之路吧!

项目结构:

Rxjava

如果你对Rxjava不了解,好吧骚年赶快学学吧,不然真会out了*******抛物线大大的金典rxjava

进阶:

Rxjava进阶一

Rxjava进阶二

Rxjava进阶三

Rxjava进阶四

ReTrofit基本设置

咱家今天的主角来了,咱们也深入浅出一下,前方高能,如果你是深度retrofit选手请直接跳过本节!!!

1.首先确保在AndroidManifest.xml中请求了网络权限

  <uses-permission android:name="android.permission.INTERNET"/>

2.在app/build.gradle添加引用

    /*rx-android-java*/
    compile 'io.reactivex:rxjava:+'
    compile 'com.squareup.retrofit:adapter-rxjava:+'
    compile 'com.trello:rxlifecycle:+'
    compile 'com.trello:rxlifecycle-components:+'
    /*rotrofit*/
    compile 'com.squareup.retrofit2:retrofit:+'
    compile 'com.squareup.retrofit2:converter-gson:+'
    compile 'com.squareup.retrofit2:adapter-rxjava:+'
    compile 'com.google.code.gson:gson:+'

ReTrofit基本使用:

后面的文章中我们都是用这个接口调试

/**
 * @api    videoLink    50音图视频链接
 * @url    http://www.izaodao.com/Api/AppFiftyToneGraph/videoLink
 * @method post
 * @param  once_no bool(选填,ture无链接) 一次性获取下载地址
 * @return json array(
 * ret:1成功,2失败
 * msg:信息
 * data:{
 *       name:视频名称
 *       title:标题
 * }
 )
 

1.初始化retrofit

要向一个api发送我们的网络请求 ,我们需要使用 Retrofit
builder
 类并指定service的base URL (通常情况下就是域名)。

    String BASE_URL = " http://www.izaodao.com/Api/"
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

2.设置接口service

注意到每个endpoint
都指定了一个关于HTTP(GET, POST, 等等。)  方法的注解以及用于分发网络调用的方法。而且这些方法的参数也可以有特殊的注解。

/**
 * 接口地址
 * Created by WZG on 2016/7/16.
 */
public interface MyApiEndpointInterface {

    @POST("AppFiftyToneGraph/videoLink")
    Call<RetrofitEntity> getAllVedio(@Body boolean once_no);
}

3.得到call然后同步处理处理回调:

        MyApiEndpointInterface apiService = retrofit.create(MyApiEndpointInterface.class);
        Call<RetrofitEntity> call = apiService.getAllVedio(true);
        call.enqueue(new Callback<RetrofitEntity>() {
            @Override
            public void onResponse(Response<RetrofitEntity> response, Retrofit retrofit) {
                RetrofitEntity entity = response.body();
                Log.i("tag", "onResponse----->" + entity.getMsg());
            }

            @Override
            public void onFailure(Throwable t) {
                Log.i("tag", "onFailure----->" + t.toString());

            }
        });

ReTrofit+Rxjava基本使用

和之前的retrofit使用区别:

1.在于我们需要修改service接口返回信息我们需要返回一个Observable对象

@POST("AppFiftyToneGraph/videoLink")
    Observable<RetrofitEntity> getAllVedioBy(@Body boolean once_no);

2.然后初始化Retrofit需要添加对Rxjava的适配,注意一定要retrofit2才有这个功能哦

Retrofit retrofit = new Retrofit.Builder()
                .client(builder.build())
                .addConverterFactory(GsonConverterFactory.create())
               .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .baseUrl(HttpManager.BASE_URL)
                .build();

3.回调交个rxjava去处理

 HttpService apiService = retrofit.create(HttpService.class);
        Observable<RetrofitEntity> observable = apiService.getAllVedioBy(true);
        observable.subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        new Subscriber<RetrofitEntity>() {
                            @Override
                            public void onCompleted() {
                            }

                            @Override
                            public void onError(Throwable e) {
                            }

                            @Override
                            public void onNext(RetrofitEntity retrofitEntity) {
                                tvMsg.setText("无封装:\n" + retrofitEntity.getData().toString());
                            }
                        }

                );

ReTrofit+Rxjava进阶封装之路

1.请求操作类封装,统一处理过程:

1.1首先初始化一个单利方便http请求

这里用了volatile的对象,不懂的同学可以参考我的另一篇博客

private volatile static HttpManager INSTANCE;
    //构造方法私有
    private HttpManager() {
        //手动创建一个OkHttpClient并设置超时时间
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        Retrofit retrofit = new Retrofit.Builder()
                .client(builder.build())
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .baseUrl(BASE_URL)
                .build();
        httpService = retrofit.create(HttpService.class);
    }

    //获取单例
    public static HttpManager getInstance() {
        if (INSTANCE == null) {
            synchronized (HttpManager.class) {
                if (INSTANCE == null) {
                    INSTANCE = new HttpManager();
                }
            }
        }
        return INSTANCE;
    }

1.2接口处理和回调处理:

basePar.getObservable主要是得打service中定义的observable对象(我们需要处理的接口对象)

RxMap方法是统一处理结果回调信息处理

basePar.getSubscirber获取需要统一结果处理的subscirber对象

/**
     * 处理http请求
     *
     * @param basePar 封装的请求数据
     */
    public void doHttpDeal(BaseEntity basePar) {
        Observable observable = basePar.getObservable(httpService)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .map(basePar);
        observable.subscribe(basePar.getSubscirber());
    }

可以发现主要的封装都放入了BaseEntity中,我们跟着思路进入到BaseEntity

2.数据统一请求参数和数据封装BaseEntity

2.1:getObservable通过传入一个**service对象获取需要处理的Observable对象

2.2:getSubScirber得到一个回调sub对象

这两个方法都需要其子类实现覆盖

2.3:在base里面我们继承Fucn1方法通过泛型去处理服务器返回数据判断(这时候我们可以在回调信息前提前处理错误信息),可以自己封装信息哦!如果是有效数据才返回给next方法,错误信息或者无数据等直接抛出一个自己定义的异常信息在onerror方法中处理!

/**
 * 请求数据统一封装类
 * Created by WZG on 2016/7/16.
 */
public abstract class BaseEntity<T> implements Func1<BaseResultEntity<T>, T> {
    /**
     * 设置参数
     *
     * @param methods
     * @return
     */
    public abstract Observable getObservable(HttpService methods);

    /**
     * 设置回调sub
     *
     * @return
     */
    public abstract Subscriber getSubscirber();
    @Override
    public T call(BaseResultEntity<T> httpResult) {
        if (httpResult.getRet() == 0) {
            throw new HttpTimeException(httpResult.getMsg());
        }
        return httpResult.getData();
    }
}

3自定义异常处理

/**
 * 自定义错误信息,统一处理返回处理
 * Created by WZG on 2016/7/16.
 */
public class HttpTimeException extends RuntimeException {

    public static final int NO_DATA = 0x2;

    public HttpTimeException(int resultCode) {
        this(getApiExceptionMessage(resultCode));
    }

    public HttpTimeException(String detailMessage) {
        super(detailMessage);
    }

    /**
     * 转换错误数据
     *
     * @param code
     * @return
     */
    private static String getApiExceptionMessage(int code) {
        String message = "";
        switch (code) {
            case NO_DATA:
                message = "无数据";
                break;
            default:
                message = "error";
                break;

        }
        return message;
    }
}

4.BaseEntity集成覆盖主要方法,实现处理的和返回的一一绑定

/**
 * 测试接口请求数据
 * Created by WZG on 2016/7/16.
 */
public class SubjectPost extends BaseEntity {
    //    回调sub
    private Subscriber mSubscriber;
    private boolean all;

    public SubjectPost(Subscriber getTopMovieOnNext, boolean all) {
        this.mSubscriber = getTopMovieOnNext;
        this.all = all;
    }

    @Override
    public Observable getObservable(HttpService methods) {
        return methods.getAllVedioBys(all);
    }

    @Override
    public Subscriber getSubscirber() {
        return mSubscriber;
    }

}

5.然后定义service接口按照泛型的方式传递返回接口的数据

  @POST("AppFiftyToneGraph/videoLink")
    Observable<BaseResultEntity<List<Subject>>> getAllVedioBys(@Body boolean once_no);

6.定义返回数据的基础类,统一处理结果信息:

/**
 * 回调信息统一封装类
 * Created by WZG on 2016/7/16.
 */
public class BaseResultEntity<T> {
    //  判断标示
    private int ret;
    //    提示信息
    private String msg;
    //显示数据(用户需要关心的数据)
    private T data;}

 7.封装回调的subservice统一处理加载框,错误提示,结果回调等处理

我们在subserice的四个回调方法中,统一处理onstart中我们现实加载框,onerror中统一处理系统错误和自定义错误信息,我们可以在baseentity的 funct1方法中统一处理返回信息,比如咱们测试方法我们可以统一判断ret参数,如果返回的是2我们抛出一个自定义的错误;或者返回的array数据为空我们也可以统一抛出一个空数据的异常!在oonext方法中我们返回一个泛型接口,传出最后service接口指定的泛型的对象!

/**
 * 用于在Http请求开始时,自动显示一个ProgressDialog
 * 在Http请求结束是,关闭ProgressDialog
 * 调用者自己对请求数据进行处理
 * Created by WZG on 2016/7/16.
 */
public class ProgressSubscriber<T> extends Subscriber<T> {
    //    回调接口
    private HttpOnNextListener mSubscriberOnNextListener;
    //    弱引用反正内存泄露
    private WeakReference<Context> mActivity;
    //    是否能取消请求
    private boolean cancel;
    //    加载框可自己定义
    private ProgressDialog pd;

    public ProgressSubscriber(HttpOnNextListener mSubscriberOnNextListener, Context context) {
        this.mSubscriberOnNextListener = mSubscriberOnNextListener;
        this.mActivity = new WeakReference<>(context);
        this.cancel = false;
        initProgressDialog();
    }

    public ProgressSubscriber(HttpOnNextListener mSubscriberOnNextListener, Context context, boolean cancel) {
        this.mSubscriberOnNextListener = mSubscriberOnNextListener;
        this.mActivity = new WeakReference<>(context);
        this.cancel = cancel;
        initProgressDialog();
    }

    /**
     * 初始化加载框
     */
    private void initProgressDialog() {
        Context context = mActivity.get();
        if (pd == null && context != null) {
            pd = new ProgressDialog(context);
            pd.setCancelable(cancel);
            if (cancel) {
                pd.setOnCancelListener(new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialogInterface) {
                        onCancelProgress();
                    }
                });
            }
        }
    }

    /**
     * 显示加载框
     */
    private void showProgressDialog() {
        Context context = mActivity.get();
        if (pd == null || context == null) return;
        if (!pd.isShowing()) {
            pd.show();
        }
    }

    /**
     * 隐藏
     */
    private void dismissProgressDialog() {
        if (pd != null && pd.isShowing()) {
            pd.dismiss();
        }
    }

    /**
     * 订阅开始时调用
     * 显示ProgressDialog
     */
    @Override
    public void onStart() {
        showProgressDialog();
    }

    /**
     * 完成,隐藏ProgressDialog
     */
    @Override
    public void onCompleted() {
        dismissProgressDialog();
    }

    /**
     * 对错误进行统一处理
     * 隐藏ProgressDialog
     *
     * @param e
     */
    @Override
    public void onError(Throwable e) {
        Context context = mActivity.get();
        if (context == null) return;
        if (e instanceof SocketTimeoutException) {
            Toast.makeText(context, "网络中断,请检查您的网络状态", Toast.LENGTH_SHORT).show();
        } else if (e instanceof ConnectException) {
            Toast.makeText(context, "网络中断,请检查您的网络状态", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(context, "错误" + e.getMessage(), Toast.LENGTH_SHORT).show();
            Log.i("tag", "error----------->" + e.toString());
        }
        dismissProgressDialog();
    }

    /**
     * 将onNext方法中的返回结果交给Activity或Fragment自己处理
     *
     * @param t 创建Subscriber时的泛型类型
     */
    @Override
    public void onNext(T t) {
        if (mSubscriberOnNextListener != null) {
            mSubscriberOnNextListener.onNext(t);
        }
    }

    /**
     * 取消ProgressDialog的时候,取消对observable的订阅,同时也取消了http请求
     */
    public void onCancelProgress() {
        if (!this.isUnsubscribed()) {
            this.unsubscribe();
        }
    }
}

8.自定义返回接口,泛型传递返回值

/**
 * 成功回调处理
 * Created by WZG on 2016/7/16.
 */
public interface HttpOnNextListener<T> {
    void onNext(T t);
}

9.发起http请求处理

定义一个指定类型的回调类httpOnextListener,然后初始化一个统一处理返回结果的ProgressSubscriber对象,将sub传入给封装的BaseEntity对象中,发起网络请求,通过Rxjava后台处理网络请求,主线程处理返回结果;网络请求onext前,调用BaseEntity的fun1方法,统一判断返回信息(可预处理错误),最后通过自定义泛型httpOnextListener返回成功数据

   //    完美封装简化版
    private void simpleDo() {
        SubjectPost postEntity = new SubjectPost(new ProgressSubscriber(simpleOnNextListener, this), true);
        HttpManager manager = HttpManager.getInstance();
        manager.doHttpDeal(postEntity);
    }

    //   回调一一对应
    HttpOnNextListener simpleOnNextListener = new HttpOnNextListener<List<Subject>>() {
        @Override
        public void onNext(List<Subject> subjects) {
            tvMsg.setText("已封装:\n" + subjects.toString());
        }
    };

啰嗦完了,如果多大家有帮助,欢迎留言哦!源代码地址

时间: 2024-10-05 11:15:07

Rxjava+ReTrofit+okHttp深入浅出-终极封装的相关文章

Rxjava+ReTrofit+okHttp深入浅出-终极封装四(多文件下载之断点续传)

Rxjava+ReTrofit+okHttp深入浅出-终极封装四(多文件下载之断点续传) 背景 断点续传下载一直是移动开发中必不可少的一项重要的技术,同样的Rxjava和Retrofit的结合让这个技术解决起来更加的灵活,我们完全可以封装一个适合自的下载框架,简单而且安全! 效果 实现 下载和之前的http请求可以相互独立,所以我们单独给download建立一个工程moudel处理 1.创建service接口 和以前一样,先写接口 注意:Streaming是判断是否写入内存的标示,如果小文件可以

Android探索之基于okHttp打造自己的网络请求&lt;Retrofit+Okhttp&gt;(五)

前言: 通过上面的学习,我们不难发现单纯使用okHttp来作为网络库还是多多少收有那么一点点不太方便,而且还需自己来管理接口,对于接口的使用的是哪种请求方式也不能一目了然,出于这个目的接下来学习一下Retrofit+Okhttp的搭配使用. Retrofit介绍: Retrofit和okHttp师出同门,也是Square的开源库,它是一个类型安全的网络请求库,Retrofit简化了网络请求流程,基于OkHtttp做了封装,解耦的更彻底:比方说通过注解来配置请求参数,通过工厂来生成CallAdap

RxJava + Retrofit 的实际应用场景

关于 RxJava Retrofit 很多篇文章都有详细的说明,在这里我想分享一个具体的使用案例,在我的开源项目 就看天气 里的实际应用.也希望跟大家探讨如何优雅的使用. 准备 项目中用到的依赖: compile 'io.reactivex:rxjava:1.1.0' compile 'io.reactivex:rxandroid:1.1.0' compile 'com.google.code.gson:gson:2.4' compile 'com.squareup.retrofit2:retr

RxJava + Retrofit完成网络请求

1.前言 本文基于RxJava.Retrofit的使用,若是对RxJava或Retrofit还不了解的简友可以先了解RxJava.Retrofit的用法再来看这篇文章. 在这片文章之前分别单独介绍过Rxjava以及Retrofit的使用: Android Retrofit 2.0 的使用 Android RxJava的使用(一)基本用法 2.使用 在了解了RxJava和Retrofit分别的用法后,RxJava.Retrofit的搭配使用也就不再话下了. 先看看使用Retrofit完成一次网络请

Retrofit+OKHttp 教你怎么持久化管理Cookie

绪论 最近小编有点忙啊,项目比较紧,所以一直在忙活项目,继之前的自定义组件之后就没再写博客了,如果你没看到之前的自定义组件你可以看一下: Android自定义下拉刷新动画–仿百度外卖下拉刷新 Android自定义组合控件-教你如何自定义下拉刷新和左滑删除 效果还行,源码也已经传到我的Github上了. 那么今天小编来给大家分享点什么呢?对,就是它:Retrofit,话说Retrofit最近真的很火啊,Retrofit+OKHttp现在似乎已经成为了Android网络请求框架的主流框架了吧,小编之

手动缓存Retrofit+OkHttp响应体,不再局限于Get请求缓存

转载请标明出处: http://blog.csdn.net/iamzgx/article/details/51764848 概括 这篇博客是接着上一篇博客学会Retrofit+OkHttp+RxAndroid三剑客的使用,让自己紧跟Android潮流的步伐,没看过的,建议看完上一篇再来看这篇.在上一篇博客中仅仅是简单的讲解了OkHttp的缓存问题,主要是通过http协议里面的control-cache控制缓存,而且是仅仅只能是Get请求才能缓存,如果Post请求OkHttp会让response返

Retrofit/OkHttp API接口加固技术实践(下)

作者/Tamic http://blog.csdn.net/sk719887916/article/details/65448628 上节加固介绍了APi单纯Post用对称加密(Base64 为列子)加密方式,这种加密方式还是存在一定的风险,加密效率虽高,但易破解,本节将介绍怎么用非对称加密 来加解密okhttp的数据,本文采用RSA加密算法为栗子. 对称加密 对称加密是最传统的加密方式,比上非对称加密,缺少安全性,但是它依旧是用的比较多的加密方法. 对称加密采用单密钥加密方式,不论是加密还是解

开发 Material Design+RxJava+Retrofit+MVP App 参考资料

前言 在开发一个基于 Material Design+RxJava+Retrofit+MVP 框架的 App 过程中学习的资料整理 —— 由G军仔分享 这里记录了我开发 大象 项目时,所学习的开发资料以及参考的开源项目,稍微整理了一下,全当笔记记录,跟大家一起分享,也许能给正在使用 RxJava + Retrofit + MVP + Material Design 框架开发的人一个参考学习,如果有人从我分享的资料当中学习到东西,那是我的荣幸,希望大家能与我一起努力. 之前看到很多人都使用 RxJ

手把手带你走进MVP +Dagger2 + DataBinding+ Rxjava+Retrofit 的世界

0.0 Android开发现在的变化用一个词来形容就是 :翻天覆地 越来越多的项目使用了MVP + Rxjava+Retrofit +Dagger2 + DataBinding等等东西.. 但是这些东西对于木有用过的同学们开起来还是比较头疼的. 转载请标明出处:http://blog.csdn.net/wingichoy/article/details/51981756 网上有很多介绍他们的教程,但是都比较详细(我听到有童鞋问:详细还不好?? 其实他们最好的学习方式还是边敲边踩坑边学,一下介绍的