RxJ2+Retrofit+OkHttp 学习分享(1)

不用多说,先上 引入需要的包

 /*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:+'
  /*Okhttp*/
    compile 'com.squareup.okhttp3:logging-interceptor:+'

如果出现错误
Warning:Conflict with dependency ‘com.google.code.findbugs:jsr305’. Resolved versions for app 异常

在您的应用程序build.gradle 条件下面这段代码,亲测试。

configurations.all { resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'}

第一步 我们要学习,Retrofit2.0 基本使用方式 我看的帖子简单好看的帖子,可以看下retrofit注解的意思就可以了。其余的咱们慢慢观察就可以了。

接下来,我们需要学习一点,rxjava2的一些基础概念,因为需要用其实有个入门概念就好。
快速通道我认为最简单,最快理解rxjava是个什么东西的帖子。
解决办法上面帖子对map和flatmap解释并没有,但是把例子用了,可能会蒙圈解释的不能在清楚了。
然后,Okhttp的学习点击这里是解释拦截器的,但是我感觉他帖子里的注释写的很棒,你看一遍就大概知道,OKhttp是怎么配置的了。毕竟,http就是网络配置的。
(其实看不看都行,因为没有用db缓存优化,虽然源码有,但是我注释了)最后 咱们看一个数据库的配置文档greendao超级简单的操作手册,了解一点基础的东西,用于数据持久化(数据库层级的缓存)。我重点说一下,先编译一下,会自动生成几个操作类,文档有说明,不然数据库操作不了。

在 RxJava 中,提供了一个名为 Scheduler 的线程调度器,RxJava 内部提供了4个调度器,分别是:

Schedulers.io(): I/O 操作(读写文件、数据库、网络请求等),与newThread()差不多,区别在于io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 效率比 newThread() 更高。值得注意的是,在 io() 下,不要进行大量的计算,以免产生不必要的线程;
Schedulers.newThread(): 开启新线程操作;
Schedulers.immediate(): 默认指定的线程,也就是当前线程;
Schedulers.computation():计算所使用的调度器。这个计算指的是 CPU 密集型计算,即不会被 I/O等操作限制性能的操作,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。值得注意的是,不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU;
AndroidSchedulers.mainThread(): RxJava 扩展的 Android 主线程;

首先盗图一张从原作者文章中盗图 其实我的分析主要来自原作者的文章原作者传送门

盗图一张

把原作者的,第一个功能的架子,已经他的类库我抽出来了。仅仅是为了看清楚结构。要是真正的使用还是用原作者的类库比较好。
先看一张结果图。


Paste_Image.png

activity重点代码

// 继承的类是Retrofit提供的。
public class MainActivity extends RxAppCompatActivity 

//单击事件的代码
  private void simpleDo() {
//        一个接口实现类 其实最核心的目的就是实现,retrofit的方法url注入的。
        SubjectPostApi postEntity = new SubjectPostApi(this, simpleOnNextListener);
        postEntity.setAll(true);
        HttpManager manager = HttpManager.getInstance();
        manager.doHttpDeal(postEntity);
    }

    //   在主线程的函数回调,用于回写数据。
    HttpOnNextListener simpleOnNextListener = new HttpOnNextListener<List<SubJectResulte>>() {
        @Override
        public void onNext(List<SubJectResulte> subjects) {
            tvMsg.setText("网络返回:\n" + subjects.toString());
        }

        @Override
        public void onCacheNext(String cache) {
            /*缓存回调*/
            Gson gson = new Gson();
            java.lang.reflect.Type type = new TypeToken<BaseResultEntity<List<SubJectResulte>>>() {
            }.getType();
            BaseResultEntity resultEntity = gson.fromJson(cache, type);
            tvMsg.setText("缓存返回:\n" + resultEntity.getData().toString());
        }

        /*用户主动调用,默认是不需要覆写该方法*/
        @Override
        public void onError(Throwable e) {
            super.onError(e);
            tvMsg.setText("失败:\n" + e.toString());
        }

        /*用户主动调用,默认是不需要覆写该方法*/
        @Override
        public void onCancel() {
            super.onCancel();
            tvMsg.setText("取消請求");
        }
    };

SubjectPostApi.class 重点代码 返回接口是一个观察者其实就是数据集合

public class SubjectPostApi extends BaseApi
//设置调用的URL方法,其实就是retrofit注入方法。这里就可以获得了你要用的那个rul 重写了这个方法。
    @Override 
    public Observable getObservable(Retrofit retrofit) {
        HttpPostService service = retrofit.create(HttpPostService.class);
        return service.getAllVedioBys(isAll());
    }

利索的看一下, HttpPostService是什么,很简单,他是一个接口就是Retrofit封装的一个url接口,通过他我们获得网络资源。。。巨简单。

public interface HttpPostService {
    @POST("AppFiftyToneGraph/videoLink")
    Call<RetrofitEntity> getAllVedio(@Body boolean once_no);

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

    @FormUrlEncoded
    @POST("AppFiftyToneGraph/videoLink")
    Observable<BaseResultEntity<List<SubJectResulte>>> getAllVedioBys(@Field("once") boolean once_no);
}

接着看看抽象类 BaseApi。这个类,这个类比较大,但是抽取重点代码就可以了,这里有个一个BaseResultEntity参数对象 后面会介绍 ,这个类其实就是关于retrofit 网络设置以及 rxjava的一个组合类 重点我们看到了。Func1这个接口他就是实现观察者的重要一个方法。从retrofit得到BaseResultEntity类型的数据 然后解释出去。

public abstract class BaseApi<T> implements Func1<BaseResultEntity<T>, T> 
一个重点参数,这个属性就是,最上面,在activity实现接口,参数回调,那必然也是这里实现的。
    private SoftReference<HttpOnNextListener> listener;
//重载了一个call方法,这个不用解释了吧,大名鼎鼎的call 就是把结果一个一个输出出来
 @Override
    public T call(BaseResultEntity<T> httpResult) {
        if (httpResult.getRet() == 0) {
            throw new HttpTimeException(httpResult.getMsg());
        }
        return httpResult.getData();
    }

一眼可以看完的,BaseResultEntity 实体类

public class BaseResultEntity<T> {
    //    错误判断
    private int ret;
    // 提示信息
    private String msg;
    //    返回的数据
    private T data;
....显示get和set方法
}

然后咱们看看 先看抽象类HttpOnNextListener 很明显,就是定义了一点点方法。

public abstract class HttpOnNextListener<T> {
    /**
     * rejava 制定下一个的方法
     */

    public abstract void onNext(T t);

    /**
     * 缓冲返回结果
     */

    public void onCacheNext(String string) {

    }

    /**
     * 成功后的ober返回,扩展链接式调用 观察者的模式
     */
    public void onNext(Observable observable) {

    }

    /**
     * 失败或错误调用的方法
     */
    public void onError(Throwable e) {

    }

    /***
     * 取消回调方法
     *
     * */
    public void onCancel() {

    }

}

重点大戏来了。HttpManager 类 这是最重要的一个方法。也是我们注入的这个合并的核心方法。 OkHttpClient 获得网络资源 retrofit获取接口结果 Observable提供数据 subscriber 解析 httpOnNextListener 回调会写到界面中。

/**
     * 处理http请求
     *
     * @param basePar 封装的请求数据
     */
    public void doHttpDeal(BaseApi basePar) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(basePar.getConnectionTime(), TimeUnit.SECONDS);
//        添加拦截器 为了例子简单,暂时注释 db持久化数据存储。仅仅是一个缓存的优化方案。
//        builder.addInterceptor(new CookieInterceptor(basePar.isCache(), basePar.getUrl()));
        if (RxRetrofitApp.isDebug()) {
            builder.addInterceptor(getHttpLoggingInterceptor());
        }

        /*创建retrofit对象*/
        Retrofit retrofit = new Retrofit.Builder()
//                客户端塞进去,这里是OKhttp和retrofit结合
                .client(builder.build())
// 适配器就是解释在rxjava中是不是见过Call方法的,看到了吗。
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .baseUrl(basePar.getBaseUrl())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        /*rx处理 订阅者 数据的解析方式,这个类其实也简单 稍后会解释*/
        ProgressSubscriber subscriber = new ProgressSubscriber(basePar);
//        被订阅者
        Observable observable = basePar.getObservable(retrofit)
                /*失败后的retry配置*/
                .retryWhen(new RetryWhenNetworkException(basePar.getRetryConut(),
                        basePar.getRetryDelay(), basePar.getRetryIncreateDalay()))
                /*生命周期管理*/
//                .compose(basePar.getRxAppCompatActivity().bindToLifecycle())
                .compose(basePar.getRxAppCompatActivity().bindUntilEvent(ActivityEvent.PAUSE))
                /*http请求线程*/
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                /*回调线程*/
                .observeOn(AndroidSchedulers.mainThread())
                /*结果判断 内容解析 这里就获得了数据*/
                .map(basePar);

 /*链接式对象返回 其实在这里这句并没有什么卵用。。。呵呵呵。*/ 
        SoftReference<HttpOnNextListener> httpOnNextListener = basePar.getListener();
        if (httpOnNextListener != null && httpOnNextListener.get() != null) {
            httpOnNextListener.get().onNext(observable);
        }

        /*数据回调 订阅*/
        observable.subscribe(subscriber);

    }

最后是ProgressSubscriber 其实他就是一个观察者。因为他继承了Subscriber 看看他的重点代码

public class ProgressSubscriber<T> extends Subscriber<T>
//这个监听 传来传去,最终,转到的他调用的地方。很不容易 
   private SoftReference<HttpOnNextListener> mSubscriberOnNextListener;

//重写 next方法,这里的就是最终解释的方法 其他的什么准备呀,开始呀,异常呀其实都可以忽略,因为核心是他。
  @Override
    public void onNext(T t) {
        if (mSubscriberOnNextListener.get() != null) {
            mSubscriberOnNextListener.get().onNext(t);
        }
    }

琐碎但是也是需要知道的几个代码
这个篇幅我并没有说GreenDAO在哪里用,源码是是有一层数据库缓存的设计思路。但是为了篇幅的思考方式我想着,这一层有没有其实不印象了解,整体的搭建。我会在后面进行解释。提一点,我们的activity 用的是RxAppCompatActivity 这个类。怕你们没有注意,我单独说一下。

好了。那么这个框架怎么用,我们要做什么东西?
其实,,咱们在鲁一下,进行拓展,多要干什么的代码?
第一步,添加接口 HttpPostService 把你要实现的url写进去,或者你单独写一个,也是可以的,
第二步,我们先显示一个 继承 BaseApi 类的代码 重写 方法,把第一步,实现的url输入进去

public Observable getObservable(Retrofit retrofit) 

第三步,在你的activtiy中实现一个类似这个样的方法,把你第二步的url注入到httpmanager中。

private void simpleDo() {
//        一个接口实现类 其实最核心的目的就是实现,retrofit的方法url注入的。
        SubjectPostApi postEntity = new SubjectPostApi(this, simpleOnNextListener);
        postEntity.setAll(true);
        HttpManager manager = HttpManager.getInstance();
        manager.doHttpDeal(postEntity);
    }

第四步:当然就是,HttpOnNextListener 这个监听 可以实现这样的一个匿名类,也可以自己写一个类,然后在向上转型,都是妥妥的。

//   在主线程的函数回调,用于回写数据。
    HttpOnNextListener simpleOnNextListener = new HttpOnNextListener<List<SubJectResulte>>() {
        @Override
        public void onNext(List<SubJectResulte> subjects) {
            tvMsg.setText("网络返回:\n" + subjects.toString());
        }

        @Override
        public void onCacheNext(String cache) {
            /*缓存回调*/
            Gson gson = new Gson();
            java.lang.reflect.Type type = new TypeToken<BaseResultEntity<List<SubJectResulte>>>() {
            }.getType();
            BaseResultEntity resultEntity = gson.fromJson(cache, type);
            tvMsg.setText("缓存返回:\n" + resultEntity.getData().toString());
        }

        /*用户主动调用,默认是不需要覆写该方法*/
        @Override
        public void onError(Throwable e) {
            super.onError(e);
            tvMsg.setText("失败:\n" + e.toString());
        }

        /*用户主动调用,默认是不需要覆写该方法*/
        @Override
        public void onCancel() {
            super.onCancel();
            tvMsg.setText("取消請求");
        }
    };

最基本的一套 合并及时专业的。我感觉,大神写库很好用考虑的很周到,修改起来吧,也很简单。再次提供大神传送地址,比我写的好传送门 大神的下载地址,他的博客有,
我项目的目录结构是这样的,比较特别是吧,主要是,我没有按照mvc方式写,而是按照 我引入类的前后顺序写的,类似思路导图的方式写的,用起来不好,仅仅是方便我个人理解类的前后关系。

我的项目目录结构

我的源码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容