不知道你有没有发现,在很多互联网公司中,RxJava在开发中占的比例越来越大。
特别是在一些发展速度快,产品迭代更新快的公司中,RxJava经常在面试中出现。
这是一篇RxJava的入门级介绍和接入教程,看完这篇文章你会明白几个问题,· RxJava 是什么· 它的优势在哪里· 怎么应用到项目中
RxJava是什么
RxJava是一个框架,也可以理解为一种代码思路。它的本质思想是观察者模式。拿我们平时经常处理的网络请求场景做例子,数据可以理解为被观察者,UI元素可以理解为观察者。UI元素会根据数据的变化做响应的改变。RxJava就是基于这么种思想的编程风格。
RxJava到现在已经发展到RxJava2了,虽然它的类名和接口名改变了不少,但实际上还是观察者模式。在RxJava中,最基础也是最根本的是两个接口,Observer 和 Observable,这跟Java中的接口名称是一样的。我们以最基础也是最简单的RxJava做demo,来感受下它能给普通的项目带来什么改变。
接入RxJava
在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也没问题,但那样就没有效率可言了。
代码对比--不使用RxJava
我们写了个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()这个方法。
代码对比--RxJava+Retrofit
没使用过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"获取源码。
==== 今日沙雕 ====