不用多说,先上 引入需要的包
/*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 主线程;
首先盗图一张从原作者文章中盗图 其实我的分析主要来自原作者的文章原作者传送门
把原作者的,第一个功能的架子,已经他的类库我抽出来了。仅仅是为了看清楚结构。要是真正的使用还是用原作者的类库比较好。
先看一张结果图。
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方式写,而是按照 我引入类的前后顺序写的,类似思路导图的方式写的,用起来不好,仅仅是方便我个人理解类的前后关系。