(声明:
本文不是讲RxJava及响应式编程的各种详细知识的。
博文主要是我学习过程的记录及搜集的资料的记录及其阅读顺序的总结,再就是资料中没有看到,自己通过源码及实践总结的一些散碎知识点。)
android中观察者模式的使用也蛮重要的。
sdk中的Observable 和Observer,EventBus,RxJava等都能很好的实现观察者模式。
首先是继承自Java的Observable 和Observer:一个Observer对象监视着一个Observable对象的变化,当Observable对象发生变化时,Observer得到通知,就可以进行相应的工作。例如在文档/视图结构中,文档被修改了,视图就会得到通知。
java.util.Observable中有两个方法对Observer特别重要,一个是setChange()方法用来设置一个内部标志位注明数据发生了变化;一个是notifyObservers()方法会去调用一个列表中所有的Observer的update()方法,通知它们数据发生了变化。
一、EventBus介绍
EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅。以及将发送者和接收者解耦。
下载EventBus的类库
源码:https://github.com/greenrobot/EventBus
EventBus比较适合仅仅当做组件间的通讯工具使用,主要用来传递消息。使用EventBus可以避免搞出一大推的interface
EventBus的使用方法可以看这篇博客
二、RxJava介绍
Rx系列涉及到响应式编程。
响应式编程可以加深你代码抽象的程度,让你可以更专注于定义与事件相互依赖的业务逻辑,而不是把大量精力放在实现细节上,同时,使用响应式编程还能让你的代码变得更加简洁。
(关于响应式编程:那些年我们错过的响应式编程)
RxJava是什么?
就是:异步。
RxJava 在 GitHub 主页上的自我介绍是 “a library for composing asynchronous and event-based programs using observable sequences for the Java VM”(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。这就是 RxJava ,概括得非常精准。
其实, RxJava 的本质可以压缩为异步这一个词。说到根上,它就是一个实现异步操作的库,而别的定语都是基于这之上的。
RxJava 好在哪?
就好在简洁,好在那把什么复杂逻辑都能穿成一条线的简洁
比如一段逻辑非常复杂,包含了多次内存操作、本地文件操作和网络操作,对象分分合合,线程间相互配合相互等待,一会儿排成人字,一会儿排成一字。如果使用常规的方法来实现,肯定是要写得欲仙欲死,然而在使用 RxJava 的情况下,依然只是一条链式调用就完成了。它很长,但很清晰。
RxJava简单使用的例子1
首先要弄清楚的几个概念:Observable 、Observer 、subscribe()
推荐: 扔物线大神的文章
创建了 Observable 和 Observer 之后,再用 subscribe() 方法将它们联结起来,整条链子就可以工作了。
具体例子:
(一)、
由 id 取得图片并显示
(由指定的一个 drawable 文件 id drawableRes 取得图片,并显示在 ImageView 中,并在出现异常的时候打印 Toast 报错)
int drawableRes = ...;
ImageView imageView = ...;
Observable.create(new OnSubscribe<Drawable>() {
@Override
public void call(Subscriber<? super Drawable> subscriber) {
Drawable drawable = getTheme().getDrawable(drawableRes));
subscriber.onNext(drawable);
subscriber.onCompleted();
}
}).subscribe(new Observer<Drawable>() {
@Override
public void onNext(Drawable drawable) {
imageView.setImageDrawable(drawable);
}
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Toast.makeText(activity, "Error!", Toast.LENGTH_SHORT).show();
}
});
创建出 Observable 和 Subscriber ,再用 subscribe() 将它们串起来,一次 RxJava 的基本使用就完成了。非常简单。
这里代码的运行逻辑是这样的:
RxJava库中的Observable即被观察者,该类中有个属性是OnSubscribe,还有一个hook。
首先,调用create(OnSubscribe)函数创建一个Observable(1)对象,并对其属性OnSubscribe进行了赋值(OnSubscribe对象含有call(Subscriber)方法)。接着,调用subscribe(Subscriber)方法创建了一个Subscriber对象,并调用了(1)(表示前文标注的对象)中实现的call()方法(此方法call中一般会调用传入的参数Subscriber对象的onNext、onComplete或者onError等方法)。
(二)、
在学习了RxJava的基本操作符的使用时,会遇到如下代码(对应map操作符):
(本代码没有什么具体功能)
Observable.create(new OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
//doing something
subscriber.onNext(s);
subscriber.onCompleted();
}
})
.map(new Func1<Integer, String>() {
@Override
public String call(Integer i) {
return String.valueOf(i);
}
})
.subscribe(new Observer<String>() {
@Override
public void onNext(String s) {
}
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Toast.makeText(activity, "Error!", Toast.LENGTH_SHORT).show();
}
});
这里代码的运行逻辑是这样的:
对比前一份代码,这里多了map()操作。
区别:在map()中调用了lift(),lift()中又重新创建了新的OnSubscribe(2)对象,并生成新的Observable从而返回。(1)中实现的call()方法是在(2)中实现的call()方法中调用的。因为传递下去的是新生成的Observable对象,根据对第一段代码的分析知道,(2)中实现的call()方法才是最后的subscribe()方法中调用的。
(三)、
(待续。。。)
然而,在 RxJava 的默认规则中,事件的发出和消费都是在同一个线程的。也就是说,如果只用上面的方法,实现出来的只是一个同步的观察者模式。观察者模式本身的目的就是『后台处理,前台回调』的异步机制,因此异步对于 RxJava 是至关重要的。而要实现异步,则需要用到 RxJava 的另一个概念: Scheduler 。
三、Retrofit网络访问框架的使用
框架简单使用的资料网上有很多
下面提供一下我自己的封装。有什么问题和建议请在下面评论处提出!多谢各位的不吝赐教。
单例模式的retrofit:
public class RetrofitHttpUtil {
public static final String InnerURL = "";//内网
public static final String PublicURL = "";//外网
public static final String ImageUrl = "";
enum URLType {innerURL, publicURL, ImageURL}
private static OkHttpClient mOkHttpClient;
private static Retrofit retrofit;
private static RetrofitInterface imageRetrofitInterface;
private static RetrofitInterface commonRetrofitInterface;
private static Object mObject = new Object();
public static RetrofitInterface getCommonRetrofitInterface() {
if (commonRetrofitInterface == null) {
Log.d("Retrofit","-------1------commonRetrofitInterface-----------is null");
synchronized (mObject) {
if (commonRetrofitInterface == null) {
Log.d("Retrofit","------2-------commonRetrofitInterface-----------is null");
commonRetrofitInterface = provideRetrofitService(URLType.innerURL);
}
}
}
return commonRetrofitInterface;
}
// public static RetrofitInterface getImageRetrofitInterface() {
// if (imageRetrofitInterface == null) {
// synchronized (mObject) {
// if (imageRetrofitInterface == null) {
// imageRetrofitInterface = provideRetrofitService(URLType.ImageURL);
// }
// }
// }
// return imageRetrofitInterface;
// }
private static void initHttpClient() {
// OkHttpClient mOkHttpClient;
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
if (httpClientBuilder.interceptors() != null) {
httpClientBuilder.interceptors().clear();
}
// httpClientBuilder.addInterceptor(new Interceptor() {
// @Override
// public Response intercept(Chain chain) throws IOException {
//
// //这里可以获取到请求的request所有数据
//// Request request = chain.request();
//// String path = request.url().encodedPath();
//// Log.d("AppClient", path + ">>>path");
//// String query = request.url().query();
//// Log.d("AppClient", query + ">>>query");
//// if (BuildConfig.DEBUG){
//// Log.d("AppClient", query + ">>>query");
//// }
// //这里设置成你的全局header
// Request interRequest = chain.request().newBuilder()
//// .headers(Headers.of(Map yourHeader))
// .build();
// return chain.proceed(interRequest);
// }
// })
httpClientBuilder.addInterceptor(logging)
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS);
mOkHttpClient = httpClientBuilder.build();
}
private static RetrofitInterface provideRetrofitService(URLType type) {
if (mOkHttpClient == null)
{ initHttpClient();
Log.d("Retrofit","-------------mOkHttpClient-----------is null");}
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(HttpUrl.parse(RetrofitHttpUtil.getUrlByLocalSetting(type)))
// for RxJava
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
//for String
.addConverterFactory(new ToStringConverterFactory())
.addConverterFactory(GsonConverterFactory.create())
.client(mOkHttpClient)
.build();
}
return retrofit.create(RetrofitInterface.class);
}
private static String getUrlByLocalSetting(URLType type) {
String url;
switch (type) {
case innerURL:
url = InnerURL;
break;
case publicURL:
url = PublicURL;
break;
case ImageURL:
url = ImageUrl;
break;
default:
url = PublicURL;
break;
}
return url;
}
}
对应的接口:
public interface RetrofitInterface {
//POST登录
String RES_USERS_LOGIN = "{path}";
@POST(RES_USERS_LOGIN)
Call<User> login(@Path("path") String path, @QueryMap Map<String, Object> body);
@POST(RES_USERS_LOGIN)
Call<String> commonConnect(@Path("path") String path, @QueryMap Map<String, Object> body);
@POST(RES_USERS_LOGIN)
Observable<String> rxCommonConnect(@Path("path") String path, @QueryMap Map<String, Object> body);
}
自定义的StringConvertFactory:
class ToStringConverterFactory extends Converter.Factory {
public static ToStringConverterFactory create(){
return new ToStringConverterFactory();
}
private static final MediaType MEDIA_TYPE = MediaType.parse("text/plain");
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
if (String.class.equals(type)) {
return new Converter<ResponseBody, String>() {
@Override public String convert(ResponseBody value) throws IOException {
return value.string();
}
};
}
return null;
}
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
if (String.class.equals(type)) {
return new Converter<String, RequestBody>() {
@Override public RequestBody convert(String value) throws IOException {
return RequestBody.create(MEDIA_TYPE, value);
}
};
}
return null;
}
// public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
// return null;
// }
}
实际使用的例子:
这里调用的login接口方法,对应使用了GSON的convertfactory。如果不想每个网络访问接口,都对应定义一个接口方法,可以使用commonConnect(),它返回字符串形式,再自己处理。
而rxCommonConnect()对应返回值是Observable,即RxJava的形式。
Map<String, String> body = new HashMap<>();
body.put("phone", userName);
body.put("pwd", pwd);
body.put("from", "0");
Call<User> call=RetrofitHttpUtil.getCommonRetrofitInterface().login("user/login",body);
call.enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
DialogUtil.dismissDialog();
Log("callString is ---"+" "+call);
Log("response is----"+" "+response.body());
}
@Override
public void onFailure(Call<User> call, Throwable t) {
DialogUtil.dismissDialog();
Log("callString is ---"+" "+call);
}
});
补充:
1、为什么你应该停止使用EventBus’
2、RxJava学习资料总结
其中:彻底搞懂系列的链接貌似失效了,我找到的新链接:http://android.walfud.com/%E5%BD%BB%E5%BA%95%E6%90%9E%E6%87%82-rxjava-%E5%9F%BA%E7%A1%80%E7%AF%87/