响应式函数式编程和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的使用方法完毕

0 0
原创粉丝点击