响应式编程android,Android响应式编程(一)RxJava[入门基础]
1.RxJava概述
ReactiveX与RxJava
在讲到RxJava之前我们首先要了解什么是ReactiveX,因为RxJava是ReactiveX的一种java实现。
ReactiveX是Reactive Extensions的缩写,一般简写为Rx,微软给的定义是,Rx是一个函数库,让开发者可以利用可观察序列和LINQ风格查询操作符来编写异步和基于事件的程序,开发者可以用Observables表示异步数据流,用LINQ操作符查询异步数据流, 用Schedulers参数化异步数据流的并发处理,Rx可以这样定义:Rx = Observables + LINQ + Schedulers。
为何要用RxJava
想到异步的操作我们会想到android的AsyncTask 和Handler,但是随着请求的数量越来越多,代码逻辑将会变得越来越复杂而RxJava却仍旧能保持清晰的逻辑。RxJava的原理就是创建一个Observable对象来干活,然后使用各种操作符建立起来的链式操作,就如同流水线一样把你想要处理的数据一步一步地加工成你想要的成品然后发射给Subscriber。
RxJava与观察者模式
RxJava的异步操作是通过扩展的观察者模式来实现的,不了解观察者模式的可以先看下设计模式(五)观察者模式这篇文章Rxjava有四个基本的要素:Observable (被观察者)、 Observer (观察者)、 subscribe (订阅)、event(事件)。Observable (被观察者) 和 Observer (观察者)通过 subscribe() 方法实现订阅关系,Observable就可以在需要的时候来通知Observer。
2.RxJava基本用法
在使用RxJava前请现在Android Studio 配置gradle:
dependencies {
...
compile 'io.reactivex:rxjava:1.1.6'
compile 'io.reactivex:rxandroid:1.2.1'
}
其中RxAndroid是RxJava的一部分,在普通的RxJava基础上添加了几个有用的类,比如特殊的调度器,后文会提到。
RxJava的基本用法分为三个步骤,他们分别是:
创建Observer(观察者)
决定事件触发的时候将有怎样的行为
Subscriber subscriber=new Subscriber() {
@Override
public void onCompleted() {
Log.i("wangshu","onCompleted");
}
@Override
public void onError(Throwable e) {
Log.i("wangshu","onError");
}
@Override
public void onNext(String s) {
Log.i("wangshu","onNext"+s);
}
@Override
public void onStart() {
Log.i("wangshu","onStart");
}
};
其中onCompleted、onError和onNext是必须要实现的方法,他们的含义分别是:
onCompleted:事件队列完结,RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。当不会再有新的 onNext发出时,需要触发 onCompleted() 方法作为完成标志。
onError:事件队列异常,在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。
onNext:普通的事件,将要处理的事件添加到事件队列中。
onStart:它会在事件还未发送之前被调用,可以用于做一些准备工作。例如数据的清零或重置,这是一个可选方法,默认情况下它的实现为空。
当然如果要实现简单的功能也可以用到Observer来创建观察者,Observer是一个接口,而上面用到Subscriber是在Observer基础上进行了扩展,在后文的Subscribe订阅过程中Observer也会先被转换为Subscriber来使用。
Observer observer = new Observer() {
@Override
public void onCompleted() {
Log.i("wangshu", "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.i("wangshu", "onError");
}
@Override
public void onNext(String s) {
Log.i("wangshu", "onNext" + s);
}
};
创建 Observable(被观察者)
它决定什么时候触发事件以及触发怎样的事件。 RxJava 使用 create() 方法来创建一个 Observable ,并为它定义事件触发规则:
Observable observable = Observable.create(new Observable.OnSubscribe() {
@Override
public void call(Subscriber super String> subscriber) {
subscriber.onNext("杨影枫");
subscriber.onNext("月眉儿");
subscriber.onCompleted();
}
});
通过调用subscriber的方法,不断的将事件添加到任务队列中,也可用just来实现:
Observable observable = Observable.just("杨影枫", "月眉儿");
上述的代码会依次调用onNext("杨影枫")、onNext("月眉儿")、onCompleted()。
Subscribe (订阅)
订阅比较简单:
observable.subscribe(subscriber);
或者也可以调用
observable.subscribe(observer);
运行代码查看log:
com.example.liuwangshu.moonrxjava I/wangshu: onStart
com.example.liuwangshu.moonrxjava I/wangshu: onNext杨影枫
com.example.liuwangshu.moonrxjava I/wangshu: onNext月眉儿
com.example.liuwangshu.moonrxjava I/wangshu: onCompleted
3.不完整定义回调
上文介绍了回调的接收主要是依赖subscribe(Observer) 和 subscribe(Subscriber),除此之外RxJava还提供了另一种回调方式,也就是不完整回调。再讲到不完整回调之前我们首先要了解Action,查看RxJava源码我们发现提供了一堆Action:
这里写图片描述
我们打开Action0来看看:
public interface Action0 extends Action {
void call();
}
再打开Action1:
public interface Action1 extends Action {
void call(T t);
}
最后看看Action9:
public interface Action9 extends Action {
void call(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9);
}
很明显Action后的数字代表回调的参数类型数量,上文订阅也就可以改写为下面的代码:
Action1 onNextAction = new Action1() {
@Override
public void call(String s) {
Log.i("wangshu", "onNext" + s);
}
};
Action1 onErrorAction = new Action1() {
@Override
public void call(Throwable throwable) {
}
};
Action0 onCompletedAction = new Action0() {
@Override
public void call() {
Log.d("wangshu", "onCompleted");
}
};
observable.subscribe(onNextAction,onErrorAction,onCompletedAction);
我们定义了onNextAction来处理onNext的回调,同理我们还定义了onErrorAction和onCompletedAction,最后我们把他传给subscribe方法。很显然这样写的灵活度很大一些,同时我们也可以只传一个或者两个Action:
observable.subscribe(onNextAction);
observable.subscribe(onNextAction,onErrorAction);
第一行只定义了onNextAction来处理onNext的回调,而第二行则定义了onNextAction处理onNext的回调,onErrorAction来处理onError的回调。
4.**Scheduler **
内置的Scheduler
方才我们所做的都是运行在主线程的,如果我们不指定线程,默认是在调用subscribe方法的线程上进行回调的,如果我们想切换线程就需要使用Scheduler。RxJava 已经内置了5个 Scheduler:
Schedulers.immediate():默认的,直接在当前线程运行,相当于不指定线程。
Schedulers.newThread():总是启用新线程,并在新线程执行操作。
Schedulers.io():I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。
Schedulers.computation():计算所使用的 Scheduler,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。
Schedulers.trampoline():当我们想在当前线程执行一个任务时,并不是立即时,可以用.trampoline()将它入队。这个调度器将会处理它的队列并且按序运行队列中每一个任务。
另外RxAndroid也提供了一个常用的Scheduler:
AndroidSchedulers.mainThread():RxAndroid库提供的Scheduler,它指定的操作在主线程中运行。
控制线程
subscribeOn() 和 observeOn() 两个方法来对线程进行控制。
subscribeOn()方法指定 subscribe() 这个方法所在的线程,即事件产生的线程。observeOn()方法指定 Subscriber 回调所运行在的线程,即事件消费的线程。
Action1 onNextAction = new Action1() {
@Override
public void call(String s) {
Log.i("wangshu", "onNext" + s);
}
};
Observable observable = Observable.just("杨影枫", "月眉儿");
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()).subscribe(onNextAction);
我们仍旧是用log打印出onNext事件所传递过来的字符串,只不过这一次事件的产生的线程是在io线程上,事件回调的线程则是在主线程。
5.**RxJava基础应用 **
好了,讲的不是很多,我们来举一个例子来消化上面的知识。RxJava+Retrofit访问网络是比较搭的,但是此前我的网络系列并没有介绍Retrofit,所以我们先准备用RxJava+OKHttp来访问网络,至于RxJava+OKHttp访问网络会在此系列的以后的章节做介绍。OKHttp的用法请详见Android网络编程(六)OkHttp3用法全解析这篇文章。
此前我们用OkHttp3访问网络是这样做的:
private void postAsynHttp(int size) {
mOkHttpClient=new OkHttpClient();
RequestBody formBody = new FormBody.Builder()
.add("size", size+"")
.build();
Request request = new Request.Builder()
.url("http://api.1-blog.com/biz/bizserver/article/list.do")
.post(formBody)
.build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String str = response.body().string();
Log.i("wangshu", str);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "请求成功", Toast.LENGTH_SHORT).show();
}
});
}
});
}
接下来我们进行改造,首先我们创建Observable(被观察者):
private Observable getObservable(final int size){
Observable observable = Observable.create(new Observable.OnSubscribe() {
@Override
public void call(final Subscriber super String> subscriber) {
mOkHttpClient=new OkHttpClient();
RequestBody formBody = new FormBody.Builder()
.add("size",size+"")
.build();
Request request = new Request.Builder()
.url("http://api.1-blog.com/biz/bizserver/article/list.do")
.post(formBody)
.build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
subscriber.onError(new Exception("error"));
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String str = response.body().string();
subscriber.onNext(str);
subscriber.onCompleted();
}
});
}
});
return observable;
}
我们将根据Okhttp的回调(不在主线程)来定义事件的规则,调用subscriber.onNext来将请求返回的数据添加到事件队列中。接下来我们来实现观察者:
private void postAsynHttp(int size){
getObservable(size).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber() {
@Override
public void onCompleted() {
Log.i("wangshu", "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.i("wangshu", e.getMessage());
}
@Override
public void onNext(String s) {
Log.i("wangshu", s);
Toast.makeText(getApplicationContext(), "请求成功", Toast.LENGTH_SHORT).show();
}
});
}
我们将事件产生也就是访问网络的操作设置为io线程,访问网络回调设置为主线程,所以Toast是能正常显示的。好了这一篇就讲到这里,关于RxJava的文章后期还会写,敬请期待。
响应式编程android,Android响应式编程(一)RxJava[入门基础]相关推荐
- 响应式编程在Android 中的一些探索
响应式在前端领域已经变得十分流行,很多主流框架都采用响应式来进行页面的展示刷新.本文主要是探索一下响应式在移动端Android上的一些实践,包括对响应式思想的理解,以及目前Android上实现响应式的 ...
- 响应式编程(反应式编程)的来龙去脉(同步编程、多线程编程、异步编程再到响应式编程)
响应式编程的来龙去脉(同步编程.多线程编程.异步编程再到响应式编程) 文章目录 响应式编程的来龙去脉(同步编程.多线程编程.异步编程再到响应式编程) 简介 1. 示例 2. 同步编程 3. 多线程编程 ...
- Android中的多线程编程与异步处理
Android中的多线程编程与异步处理 引言 在移动应用开发中,用户体验是至关重要的.一个流畅.高效的应用能够吸引用户并提升用户满意度.然而,移动应用面临着处理复杂业务逻辑.响应用户输入.处理网络请求 ...
- android应用的界面编程----View与ViewGroup的概念
1 UI OverView Android中所有的UI元素都是通过View与ViewGroup来构建的,View是指屏幕中一块可与用户进行交互的空白,类似于java界面编程中的JPanel.为了界面布 ...
- html响应式弹性布局,CSS3响应式布局之弹性盒子
CSS3弹性盒模型可以轻松的创建自适应浏览器流动窗口的布局或自适应字体大小的布局.同时该盒子决定了一个盒子在其他盒子的分布方式,及如何处理可用的空间. 自己写了一个弹性盒子的demo: 主要HTML代 ...
- android开发高级开发,Android多媒体开发高级编程 (Shawn Van Every) pdf扫描版
<android多媒体开发高级编程--为智能手机和平板电脑开发图形.音乐.视频和富媒体应用>使用清晰.直观的示例介绍了android sdk中丰富的多媒体功能,有助于您开发能够创建.播放和 ...
- android编程高级教程 pdf,Android多媒体开发高级编程
在多媒体功能方面,今天的手机同时是照相机.相册.摄像机.电影播放器.音乐播放器.听写机,且可能具备更多功能. 特别是,Android在SDK中具有非常丰富的功能,本书将试图通过讨论和实例对该SDK进行 ...
- Android项目驱动式开发教程 第2版,《Android项目驱动式开发教程》第一章开发入门.ppt...
<Android项目驱动式开发教程>第一章开发入门 1.4 项目框架分析 4 android:versionName="1.0" > 5 8 第9行代码andro ...
- Android的沉浸式状态栏与变色状态栏详解
此文章装载至http://www.androidchina.net/3520.html点击打开链接 一. 首先我们得了解什么是透明状态栏以及什么是沉浸式状态栏,以及其区别,国内习惯称透明状态栏为沉浸式 ...
最新文章
- 在docker上安装部署tomcat项目 超简单,拿来主义
- debug调到循环最后_Java入门(7)——循环和debug 调试
- 全网独家分享,软件测试就该这么学,3个月进大厂!
- 手机锁屏密码忘记了怎么办,清除锁屏的办法
- 24.23%!汉能高效硅异质结薄膜电池效率再次刷新中国纪录
- vue创建项目自定义配置
- linux查看java堆栈
- OV5640时钟理解与端口理解(一)
- 编写函数:字符串的小写转大写(Append Code)
- 华为的芯片战略:别忘记,代号—SD502!
- 三角形面积的勾股定理
- SIGCOMM‘2021 Congestion Detection in Lossless Networks 阅读笔记
- gcc 编译选项常用参数(-S -c -E -o)
- 闭包是什么?五分钟带你了解闭包
- 前程无忧“病情”加重
- 2017年小老虎博客排名与访问量备忘录
- 计算机缺少什么无法正常启动,应用无法正常启动是什么意思
- UE4第一人称游戏 ——(3)添加准星
- Python3.6实现12306火车票自动抢票,附源码
- 关于SNMP远程管理端连接不上设备代理端问题
热门文章
- 快速梳理23种常用的设计模式
- 爬取北京链家二手房(requests和selenium)
- CVPR2022《BatchFormer: Learning to Explore Sample Relationships for Robust Representation Learning》
- 某东网页版自动好评脚本使用教程
- 积分竟然比微分早了1300年!一文讲清积分的历史
- 2017百度之星 资格赛1003度度熊与邪恶大魔王
- 05 pyecharts 基本图表(示例代码+效果图)
- 召回率 matlab代码,召回率和精度(示例代码)
- 逆天了word 90后:情人节巧用小小技术就俘获了女神
- 我的2020年终总结