前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >五分钟带你感受RxJava的优雅

五分钟带你感受RxJava的优雅

作者头像
PhoenixZheng
发布2018-09-29 11:39:04
6070
发布2018-09-29 11:39:04
举报

不知道你有没有发现,在很多互联网公司中,RxJava在开发中占的比例越来越大。

特别是在一些发展速度快,产品迭代更新快的公司中,RxJava经常在面试中出现。

这是一篇RxJava的入门级介绍和接入教程,看完这篇文章你会明白几个问题, · RxJava 是什么 · 它的优势在哪里 · 怎么应用到项目中

RxJava是什么

RxJava是一个框架,也可以理解为一种代码思路。 它的本质思想是观察者模式。拿我们平时经常处理的网络请求场景做例子,数据可以理解为被观察者,UI元素可以理解为观察者。UI元素会根据数据的变化做响应的改变。RxJava就是基于这么种思想的编程风格。

RxJava到现在已经发展到RxJava2了,虽然它的类名和接口名改变了不少,但实际上还是观察者模式。在RxJava中,最基础也是最根本的是两个接口,Observer 和 Observable,这跟Java中的接口名称是一样的。 我们以最基础也是最简单的RxJava做demo,来感受下它能给普通的项目带来什么改变。

接入RxJava

在Android中引入RxJava需要添加两个依赖,RxJava和RxAndroid

代码语言:javascript
复制
implementation 'io.reactivex:rxjava:1.3.8'
implementation 'io.reactivex:rxandroid:1.2.1'

demo中的例子是用Retrofit来作为网络请求框架,所以还需要添加 Retrofit 的依赖

代码语言:javascript
复制
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 类。

代码语言:javascript
复制
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接口定义是这样的

代码语言:javascript
复制
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的代码的差别在哪里。

代码语言:javascript
复制
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转换的模板代码,它都有现成的工具类帮你实现,

代码语言:javascript
复制
.addConverterFactory(GsonConverterFactory.create())//<--Gson转换代码
总结

所以说为什么越来越多的公司开始普及RxJava,我觉得有几个原因 · 线程切换 · 链式调用 · 兼容性好 RxJava还有一些更好的特性,这里篇幅所限,我们接下来再陆续举例说明。 如果你看了这篇文章想要拿对应的demo来学习的话,可以在后台回复"RxJava"获取源码。

==== 今日沙雕 ====

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-09-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android每日一讲 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • RxJava是什么
  • 接入RxJava
  • 代码对比--不使用RxJava
  • 代码对比--RxJava+Retrofit
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档