不知道你有没有发现,在很多互联网公司中,RxJava在开发中占的比例越来越大。
特别是在一些发展速度快,产品迭代更新快的公司中,RxJava经常在面试中出现。
这是一篇RxJava的入门级介绍和接入教程,看完这篇文章你会明白几个问题, · RxJava 是什么 · 它的优势在哪里 · 怎么应用到项目中
RxJava是一个框架,也可以理解为一种代码思路。 它的本质思想是观察者模式。拿我们平时经常处理的网络请求场景做例子,数据可以理解为被观察者,UI元素可以理解为观察者。UI元素会根据数据的变化做响应的改变。RxJava就是基于这么种思想的编程风格。
RxJava到现在已经发展到RxJava2了,虽然它的类名和接口名改变了不少,但实际上还是观察者模式。在RxJava中,最基础也是最根本的是两个接口,Observer 和 Observable,这跟Java中的接口名称是一样的。 我们以最基础也是最简单的RxJava做demo,来感受下它能给普通的项目带来什么改变。
在Android中引入RxJava需要添加两个依赖,RxJava和RxAndroid
implementation 'io.reactivex:rxjava:1.3.8'
implementation 'io.reactivex:rxandroid:1.2.1'
demo中的例子是用Retrofit来作为网络请求框架,所以还需要添加 Retrofit 的依赖
implementation 'com.squareup.retrofit2:retrofit:2.0.0'
implementation 'com.squareup.retrofit2:converter-gson:2.0.0'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.0.0'
可能你是第一次用Retrofit还不了解它。OkHttp用过吧?OkHttp是以 Android的 HttpUrlConnection作为基础,封装起来的网络请求库。而Retrofit是以OkHttp为基础封装起来的更简洁的网络请求库,它跟OkHttp是同一个公司的出品。 使用Retrofit的原因不仅因为它封装了更简洁的接口,还因为它兼容RxJava。当然你说不用它也可以,OkHttp同样能做一样的事情,甚至手撸HttpUrlConnection也没问题,但那样就没有效率可言了。
我们写了个demo,用来请求某地区的天气情况,然后更新到UI。 demo中用OkHttp来做网络请求,请求返回的json结果封装成 WeatherBean 类。
private void getWeatherJava() {
final Request request = new Request.Builder().url(getWeatherUrl()).build();
okhttp3.Call call = OKHttpManager.getInstance().getClient().newCall(request);
call.enqueue(new okhttp3.Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
Log.d(TAG, "onFailure: " + e.getMessage());
}
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
try {
if(response.body() != null) {
String body = response.body().string();
Log.d(TAG, "onResponse: " + body);
Type type = new TypeToken<WeatherBean>() {}.getType();
WeatherBean bean = new Gson().fromJson(body, type); //<--请求结果
WeatherActivity.this.runOnUiThread(new Runnable() { //<--切换到主线程
@Override
public void run() {
invalidateWeather(bean);
}
});
}
} catch (Exception e) {
Log.d(TAG, "onResponse: " + e.getMessage());
}
}
});
}
/**
* @param bean 请求结果
*/
private void invalidateWeather(WeatherBean bean) {
mLocation.setText(bean.getSys().getCountry());
mTmp.setText(String.valueOf(bean.getMain().getTemp()));
}
/**
* @return 某地区天气请求的url
*/
private String getWeatherUrl() {
String location = "Beijing";
return String.format(AppConstant.URL_CITY, location, AppConstant.APP_KEY);
}
这段代码一目了然,这里需要强调一点,在网路请求返回的时候关于线程的问题。 对于网络请求这种耗时操作都要开线程去处理,OkHttp在请求结束返回时是处于子线程的。 子线程不允许更新UI的问题相信大家都知道,所以这里需要post到当前的Activity去更新UI。
挺简单的一段代码,但我们还是觉得太繁琐。 现在我们要用RxJava+Retrofit来修改getWeatherJava()这个方法。
没使用过Retrofit的话可能需要补充一下相应的知识点。如果懒的跳去看的话也没关系,因为这篇文章的目的是感受RxJava带来的优势和便利性,即使不懂Retrofit,也一样能从代码上感受出来。你可以选择跳过看不懂的地方,直接跳到最后面的 getWeatherRetrofitRx()源码。
这个demo中的Retrofit接口定义是这样的
public interface ApiWeather {
@GET("/data/2.5/weather")
Observable<WeatherBean> getWeather(@Query("q") String city, @Query("APPID") String appid);
}
如果你用过Retrofit,这里能看到区别。Retrofit的接口通常是返回Call对象,而这里返回的是Observable对象。这就是Retrofit兼容RxJava的地方,它能直接生成一个Observable对象给RxJava作为链式调用的接收者,所以这也是为什么Retrofit+RxJava能让代码非常优雅的原因。
直接上代码,看看跟用OkHttp的代码的差别在哪里。
private void getWeatherRetrofitRx() {
Retrofit retrofit = new Retrofit.Builder()
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())//<--Gson转换代码
.baseUrl(AppConstant.ULR)
.build();
ApiWeather apiWeather = retrofit.create(ApiWeather.class);
apiWeather.getWeather("Beijing", AppConstant.APP_KEY)
.subscribeOn(Schedulers.io()) //<--切换到子线程做网络请求
.observeOn(AndroidSchedulers.mainThread()) //<--切换到主线程做UI更新
.subscribe(new Observer<WeatherBean>() {
@Override
public void onCompleted() {
Log.d(TAG, "onCompleted: ");
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError: ");
}
@Override
public void onNext(WeatherBean bean) {
Log.d(TAG, "onNext: ");
invalidateWeather(bean);
}
});
}
这段代码是不是非常的简洁?这样就完成了一次网络的请求和UI更新。
链式调用+统一缩进,比用OkHttp的代码的阅读性提升了许多。但它的优势不仅如此,RxJava其中一个很重要的特性才是它被普遍使用的原因。
那就是线程切换
。
上面说了,网络请求是在子线程中操作,而更新UI必须在主线程。这也是用OkHttp写的代码读起来难受的原因,因为需要写繁琐的代码去切换线程。甚至在场景复杂的情况下,还需要手撸handler去做这些事情。 RxJava免去了这些烦恼,可以看上面这段代码的注释关于线程切换的部分。 当你需要把操作放到子线程,只需要subscribeOn(Schedulers.io()) 当你需要在主线程做响应,只需要observeOn(AndroidSchedulers.mainThread())
而Retrofit还不用你手写Gson转换的模板代码,它都有现成的工具类帮你实现,
.addConverterFactory(GsonConverterFactory.create())//<--Gson转换代码
所以说为什么越来越多的公司开始普及RxJava,我觉得有几个原因 · 线程切换 · 链式调用 · 兼容性好 RxJava还有一些更好的特性,这里篇幅所限,我们接下来再陆续举例说明。 如果你看了这篇文章想要拿对应的demo来学习的话,可以在后台回复"RxJava"获取源码。
==== 今日沙雕 ====