什么是函数响应式编程(JavaAndroid版本)

什么是函数响应式编程(Java&Android版本)

——欢迎转载,请注明出处 ,未经本人同意请勿用于商业用途,谢谢——

原文链接:

函数响应式编程(FRP)为解决现代编程问题提供了全新的视角。一旦理解它,可以极大地简化你的项目,特别是处理嵌套回调的异步事件,复杂的列表过滤和变换,或者时间相关问题。

我将尽量跳过对函数响应式编程学院式的解释(网络上已经有很多),并重点从实用的角度帮你理解什么是函数响应式编程,以及工作中怎么应用它。本文将围绕函数响应式编程的一个具体实现RxJava,它可用于Java和Android。

开始

我们以一个真实的例子来开始讲解函数响应式编程怎么提高我们代码的可读性。我们的任务是通过查询GitHub的API,首先获取用户列表,然后请求每个用户的详细信息。这个过程包括两个web 服务端点: https://api.github.com/users – 获取用户列表; https://api.github.com/users/{username} -获取特定用户的详细信息,例如https://api.github.com/users/mutexkid。

旧的风格

下面例子你可能已经很熟悉了:它调用web service,使用回调接口将成功的结果传递给下一个web service请求,同时定义另一个成功回调,然后发起下一个web service请求。你可以看到,这会导致两层嵌套的回调:

() {//first, request the users…mService.requestUsers(new Callback<GithubUsersResponse>() {(final GithubUsersResponse githubUsersResponse,final Response response) {Timber.i(TAG, “Request Users request completed”);final synchronized List<GithubUserDetail> githubUserDetails = new ArrayList<GithubUserDetail>();//next, loop over each item in the responsefor (GithubUserDetail githubUserDetail : githubUsersResponse) {//request a detail object for that usermService.requestUserDetails(githubUserDetail.mLogin,new Callback<GithubUserDetail>() {(GithubUserDetail githubUserDetail,Response response) {Log.i(“User Detail request completed for user : ” + githubUserDetail.mLogin);githubUserDetails.add(githubUserDetail);if (githubUserDetails.size() == githubUsersResponse.mGithubUsers.size()) {//we’ve downloaded’em all – notify all who are interested!mBus.post(new UserDetailsLoadedCompleteEvent(githubUserDetails));}}(RetrofitError error) {Log.e(TAG, “Request User Detail Failed!!!!”, error);}});}}(RetrofitError error) {Log.e(TAG, “Request User Failed!!!!”, error);}});}

尽管这不是最差的代码-至少它是异步的,因此在等待每个请求完成的时候不会阻塞-但由于代码复杂(增加更多层次的回调代码复杂度将呈指数级增长)因此远非理想的代码。当我们不可避免要修改代码时(在前面的web service调用中,我们依赖前一次的回调状态,因此它不适用于模块化或者修改要传递给下一个回调的数据)也远非容易的工作。我们亲切的称这种情况为“回调地狱”。

RxJava的方式

下面让我们看看使用RxJava如何实现相同的功能:

public void rxFetchUserDetails() {//request the usersmService.rxRequestUsers().concatMap(Observable::from).concatMap((GithubUser githubUser) ->//request the details for each usermService.rxRequestUserDetails(githubUser.mLogin))//.toList()//.subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread())//.subscribe(githubUserDetails -> {EventBus.getDefault().post(new UserDetailsLoadedCompleteEvent(githubUserDetails));});}

如你所见,使用函数响应式编程模型我们完全摆脱了回调,并最终得到了更短小的程序。让我们从函数响应式编程的基本定义开始慢慢解释到底发生了什么,并逐渐理解上面的代码,这些代码托管在GitHub上面。

从根本上讲,函数响应式编程是在观察者模式的基础上,增加对Observables发送的数据流进行操纵和变换的功能。在上面的例子中,Observables是我们的数据流通所在的管道。

回顾一下,观察者模式包含两个角色:一个Observable和一个或者多个Observers。Observable发送事件,而Observer订阅和接收这些事件。在上面的例子中,.subscribe()函数用于给Observable添加一个Observer,并创建一个请求。

构建一个Observable管道

对Observable管道的每个操作都将返回一个新的Observable,这个新的Observable的内容要么和操作前相同,要么就是经过转换的。这种方式使得我们可以对任务进行分解,并把事件流分解成小的操作,,接着把这些Observables拼接起来从而完成更复杂的行为或者重用管道中的每个独立的单元。我们对Observable的每个方法调用会被加入到总的管道中以便我们的数据在其中流动。

下面首先让我们从搭建一个Observable开始,来看一个具体的例子:

Observable<String> sentenceObservable = Observable.from(“this”, “is”, “a”, “sentence”);

这样我们就定义好了管道的第一个部分:Observable。在其中流通的数据是一个字符串序列。首先要认识到的是这是没有实现任何功能的非阻塞代码,仅仅定义了我们想要完成什么事情。Observable只有在我们“订阅”它之后才会开始工作,也就是说给它注册一个Observer之后。

Observable.subscribe(new Action1<String>() {@Override(String s) {System.out.println(s);} });

到这一步Observable才会发送由每个独立的Observable的from()函数添加的数据块。管道会持续发送Observables直到所有Observables都被处理完成。

变换数据流涉水而过的声音此次想起,

什么是函数响应式编程(JavaAndroid版本)

相关文章:

你感兴趣的文章:

标签云: