响应式函数式编程和RxJava的理解
来源:互联网 发布:linux tomcat运行缓慢 编辑:程序博客网 时间:2024/05/16 01:24
面向函数式编程, 即会将函数作为一个数据对象.下面看Android中RxJava的实现
RxJava 是一个观察者模式的扩展:
RxJava 一个观察者模式的扩展,
观察者模式: 比如Button的点击事件,对设置 OnClickListener 来说, Button 是被观察者, OnClickListener 是观察者,二者通过 setOnClickListener() 方法产生关系。
OnClickListener一直观察着Button,当Button被点击,OnClickListener执行onClick事件。
而RxJava中 Observable(可观察的,被观察者),Observer(观察者),subscribe(订阅),事件;Observable和Observer
之间通过subscribe()方法实现订阅关系,从而Observable可以在需要的时候发出事件来通知Observer
以下的Demo即为几个实现的小例子
TestActivity是RxJava几个关键字的用法; 被观察者订阅观察者, 被观察者提供数据, 观察者观察到数据的变化, onNext()方法中得到数据, 处理数据
package com.example.mytestrxjava;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import rx.Observable;import rx.Observer;import rx.Subscriber;import rx.functions.Action0;import rx.functions.Action1;import rx.functions.Func1;/*响应式函数编程RxJava 一个观察者模式的扩展,观察者模式: 比如Button的点击事件,对设置 OnClickListener 来说, Button 是被观察者, OnClickListener 是观察者,二者通过 setOnClickListener() 方法产生关系。 OnClickListener一直观察着Button,当Button被点击,OnClickListener执行onClick事件。 而RxJava中 Observable(可观察的,被观察者),Observer(观察者),subscribe(订阅),事件;Observable和Observer 之间通过subscribe()方法实现订阅关系,从而Observable可以在需要的时候发出事件来通知Observer 以下的Demo即为几个实现的小例子 */public class TestActivity extends AppCompatActivity { public static final String TAG = "AppCompatActivity"; private String[] words = {"aaaa", "bbbb", "cccc"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); } public void onClick(View view) { switch (view.getId()) { case R.id.btn_sample: test(); break; case R.id.btn_just: just(); break; case R.id.btn_from: myFrom(); break; case R.id.btn_action: action(); break; case R.id.btn_map: map(); break; case R.id.btn_flatmap: flatmap(); break; case R.id.btn_filter: filter(); break; } } private void test() { //被观察者 Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext("aaaa"); subscriber.onNext("bbbb"); subscriber.onNext("cccc"); subscriber.onCompleted(); } }); //观察者 Observer<String> observer = new Observer<String>() { @Override public void onCompleted() { Log.e(TAG,"onCompleted"); } @Override public void onError(Throwable e) { Log.e(TAG,"Error" + e.toString()); } @Override public void onNext(String s) { Log.e(TAG,s); } }; //被观察者 订阅观察者 observable.subscribe(observer); } private void just() { //使用just 不用重写call方法, 被观察者 Observable<String> observable = Observable.just("aaa2","bbb2","ccc2"); Observer<String> observer = new Observer<String>() { @Override public void onCompleted() { Log.e(TAG, "onCompleted"); } @Override public void onError(Throwable e) { Log.e(TAG, "Error" + e.toString()); } @Override public void onNext(String s) { Log.e(TAG, s); } }; observable.subscribe(observer); } /** 当传入的是一个数组的时候 , 可以使用from*/ private void myFrom() { Observable<String> observable = Observable.from(words); Observer<String> observer = new Observer<String>() { @Override public void onCompleted() { Log.e(TAG, "onCompleted"); } @Override public void onError(Throwable e) { Log.e(TAG, "Error" + e.toString()); } @Override public void onNext(String s) { Log.e(TAG, s); } }; observable.subscribe(observer); } /** 不是订阅一个观察者, 而是订阅一个单独执行的任务 */ private void action() { Action1 action1 = new Action1<String>() { @Override public void call(String s) { Log.e(TAG,s); } }; Action1 action2 = new Action1<Throwable>() { @Override public void call(Throwable e) { Log.e(TAG, "Error" + e.toString()); } }; Action0 action3 = new Action0() { @Override public void call() { Log.e(TAG,"oncompleted"); } }; Observable<String> observable = Observable.from(words); observable.subscribe(action1); observable.subscribe(action1,action2); observable.subscribe(action1,action2,action3); } /** * 被观察者进行数据转换, 如果我们希望传入的是String类型,而处理的类型是int类型 */ private void map() { Observable.just("aaa","bbb","ccc") .map(new Func1<String, Integer>() { @Override public Integer call(String s) { return s.length(); } }) .subscribe(new Action1<Integer>() { @Override public void call(Integer integer) { Log.e(TAG,"length" + integer); //因为传入了三个对象, 所以被调用了三次 } }) ; } /** * flapMap()中返回的是个Observable对象,并且这个Observable对象并不是被直接发送到了 * Subscriber回调方法中. * 例如下面的例子,可以看做是,一个String返回了一个Observable,一个Observable执行了三次Action */ private void flatmap() { Observable.just("aaaa","bbb","cc") .flatMap(new Func1<String, Observable<Integer>>() { @Override public Observable<Integer> call(String s) { Integer[] info = new Integer[3]; info[0] = s.length(); info[1] = s.hashCode(); info[2] = s.getBytes().length; return Observable.from(info); //有数组可以使用from关键字 } }).subscribe(new Action1<Integer>() { @Override public void call(Integer integer) { Log.e(TAG,integer+""); } }); } /** * filter指定过滤 * 比如我指定过滤字符串中含有"a"的字符串 */ private void filter() { //一句话链式编程解决文字, 被观察者订阅了观察者 Observable.from(words) .filter(new Func1<String, Boolean>() { @Override public Boolean call(String s) { return s.contains("a"); } }) .subscribe(new Observer<String>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(String s) { Log.e(TAG,"过滤的字符串为" + s); } }); }}
线程管理Scheduler使用:
在不指定线程的情况下, RxJava 遵循的是线程不变的原则,即:在哪个线程调用 subscribe(),就在哪个线程生产事件;在哪个线程生产事件,就在哪个线程消费事件。如果需要切换线程,就需要用到 Scheduler (调度器)。
Schedulers.immediate(): 直接在当前线程运行,相当于不指定线程。这是默认的 Scheduler。
Schedulers.newThread(): 总是启用新线程,并在新线程执行操作。
Schedulers.io(): I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。
Schedulers.computation(): 计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。
另外, Android 还有一个专用的AndroidSchedulers.mainThread(),它指定的操作将在 Android 主线程运行。
下面的Demo ImageActivity就是在网络上获取图片然后展示的例子
package com.example.mytestrxjava;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.widget.ImageView;import android.widget.Toast;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import rx.Observable;import rx.Observer;import rx.Subscriber;import rx.android.schedulers.AndroidSchedulers;import rx.schedulers.Schedulers;public class ImageActivity extends AppCompatActivity { private static final String TAG = "ImageActivity"; public static String imageurl = "https://mobile.umeng.com/images/pic/home/social/img-1.png"; private ImageView mIv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_image); mIv = (ImageView) findViewById(R.id.iv); init(); } private void init() { //被观察者 Observable<Bitmap> observable = Observable.create(new Observable.OnSubscribe<Bitmap>() { @Override public void call(Subscriber<? super Bitmap> subscriber) { byte[] data = getNetData(); Bitmap bitmap1 = binary2Bitmap(data); subscriber.onNext(bitmap1); //在IO线程, 且订阅者对象将数据传递给观察者 subscriber.onCompleted(); } }) .subscribeOn(Schedulers.io()) //指定subscribe()发生在IO线程 .observeOn(AndroidSchedulers.mainThread()) //指定Subscriber的回调发生在主线程 ; //观察者 Observer<Bitmap> observer = new Observer<Bitmap>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { Toast.makeText(ImageActivity.this,e.toString(),Toast.LENGTH_SHORT).show(); } @Override public void onNext(Bitmap bitmap) { //观察者对 被观察者给的数据进行处理 Log.e(TAG,"bitmap:" + bitmap.toString()); mIv.setImageBitmap(bitmap); } }; observable.subscribe(observer); } /** * 将byte[]数组数据 转化为BItmap对象 * @param data * @return */ private Bitmap binary2Bitmap(byte[] data) { if(data != null) { return BitmapFactory.decodeByteArray(data,0,data.length); } return null; } /** * 从网络获取图片的数据,得到字节数据 * @return */ private byte[] getNetData() { ByteArrayOutputStream boas = null; InputStream in = null; try { boas = new ByteArrayOutputStream(); URL url = new URL(imageurl); //异常抓取 HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setConnectTimeout(2000); in = httpURLConnection.getInputStream(); byte[] buf = new byte[4 * 1024]; int b; while ((b = in.read(buf)) != -1) { boas.write(buf,0,b); } Log.e(TAG,boas.toString()); return boas.toByteArray(); } catch (Exception e) { e.printStackTrace(); return null; }finally { //流的异常处理 if(in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); }finally { if(boas != null) { try { boas.close(); } catch (IOException e) { e.printStackTrace(); } } } } } }}
由于网络请求要放在子线程,所以使用Schedulers.io(), 而回调需要设置ImageView, 需要放到主线程,所以使用AndroidSchedulers.mainThread()
至此,Rxjava的使用方法完毕
- 响应式函数式编程和RxJava的理解
- RxJava响应式函数编程
- RxJava响应式函数编程
- Android函数响应式编程——RxJava的4大subject和线程控制
- 响应式编程Rxjava
- RxJava响应式编程
- RXJAVA响应式编程
- RxJava响应式编程
- 响应式编程架构RxJava
- RxJava 之 响应式编程
- 响应式编程架构RxJava
- RxJava(响应式函数编程)初体验
- Android函数响应式编程最新RxJava-基本用法(1)
- Android函数响应式编程最新RxJava-线程控制
- Android之RxJava函数响应式编程(一)基本用法
- 【RxJava】RxJava响应式带来的好处
- Android中基于RxJava的响应式编程
- 响应式编程--Android Rxjava的使用(一)
- JS Datatables插件server-side方式处理分页的示例代码段
- JSP实现分页功能(转自其他地方)
- ASP.NET Web Pages – 添加 Razor 代码
- 文章标题
- linux socket
- 响应式函数式编程和RxJava的理解
- 自组织映射神经网络SOM--学习小记[2]
- angularjs实现任意点击一个标签,指定的标签展开,其他的标签闭合
- 简单理解AOP(面向切面编程)
- DateFormat工具类
- 开发中遇到的Mac使用问题
- iOS语言本地化/国际化
- iBeacon介绍
- [硕.Love Python] BinarySearchTree(二叉搜索树)