RxJava(二)歪论

来源:互联网 发布:java小软件源代码 编辑:程序博客网 时间:2024/06/06 19:18

        如果你看到这里,我猜你看过不少Rxjava的博客、文章了。

        去XX的观察者、被观察者、注册、订阅,分分钟搞晕。

        我觉得换个称呼会好一点:生产者和消费者。如果你已经习惯了观察者和被观察者的称呼----那你肯定明白他们和生产消费者之间的对应关系。

        强推一篇文章,不是强烈推荐,是强行推荐:扔物线的文章

        还有另一篇关于理解的文章:NotRxJava懒人专用指南   

        有了上面这么好的文章,我为什么还再自己写一篇呢?CSDN这个月还差一篇当你试着记下来写思路的时候,你思考如何去清晰的表达会让你对这件事加深理解。而且我也不写什么原理、道理、哲理,我就说什么效果怎么用。所以这篇文章的总结就是:我就不讲理了!

第一部分  三段式

        范式:Observable.subscribe(subscriber/observer)

        就是通过生产者(第一段)的subscribe方法(第二段)将消费者(第三段)联系起来。

 

        通常的生产者有三种产生方法:create(), just(),from(); defer有点偏,这里先不说了。

        消费者先说两种,Observer和Subscriber。

        先来一套流程看看:

    //生产部分1, 产生一条内容    public Observable<String> strObservable1 = Observable.create(new Observable.OnSubscribe<String>() {        @Override        public void call(Subscriber<? super String> subscriber) {            subscriber.onNext("人之初");//”人之初”三个字通过onNext发货了            subscriber.onCompleted();        }    });
    //消费部分    private Subscriber subscriber = new Subscriber<String>() {        @Override        public void onCompleted() {            Toast.makeText(mContext,"结束",Toast.LENGTH_SHORT).show();        }        @Override        public void onError(Throwable e) {            Toast.makeText(mContext,"数据异常",Toast.LENGTH_SHORT).show();        }        @Override        public void onNext(String o) {            Toast.makeText(mContext,o,Toast.LENGTH_SHORT).show();        }    };

//联系起来strObservable1.subscribe(observer);

        “生产者”生产“人之初”,通过subscribe()传递到了消费者,Toast显示。



        这里必须说:代码量增加了几倍,似乎这个就是一句话就搞定的玩意,居然写了这么多,是不是制杖?

 

        一次生产消费一个东西,很不实用啊,接下来就正式说如何生产多个:

        不想废话,直接代码

    //生产部分2发送多条内容    public Observable<String> strObservable2 = Observable.create(new Observable.OnSubscribe<String>() {        @Override        public void call(Subscriber<? super String> subscriber) {            subscriber.onNext("人之初");            subscriber.onNext("性本善");            subscriber.onNext("性相近");            subscriber.onNext("习相远");            subscriber.onCompleted();        }    });    //生产部分3  上面的代码写的好累啊?那就使用just发送多条内容    public Observable<String> strObservable3 = Observable.just("人之初","性本善","性相近","习相远");    //生产部分4  just感觉不够灵活?使用from和数组发送多条内容    String[] threeWordJing = {"人之初","性本善","性相近","习相远"};    public Observable<String> strObservable4 = Observable.from(threeWordJing);

        然后让它们和“消费者”产生联系,就OK了。

        效果如下:


        关于消费者的Observer在形式上和Subscriber几乎没区别,代码忽略了。 

 

        如果一件事只是发生,我们不关注或者忽略结果,那么按照上面的三段式就显得浪费了,也可以说不优雅了,那么说一下三段式的变式:二段式(其实就是“消费者”部分)。有这样的业务吗?管他呢!

        Observable.create(new Observable.OnSubscribe<Void>() {            @Override            public void call(Subscriber<? super Void> subscriber) {                startActivity(new Intent(mContext,MainActivity.class));                TernaryFormActivity.this.finish();            }        }).subscribe();

        为什么不可以“一段式”呢?因为一段式不执行。哈哈哈

        贴一下整个类的代码,然后开始下一部分:

package com.shareye.rxtestbydemo;import android.content.Context;import android.content.Intent;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.widget.Toast;import butterknife.ButterKnife;import butterknife.OnClick;import rx.Observable;import rx.Observer;import rx.Subscriber;/** * Created by ShuaiZhang on 2016/7/25. */public class TernaryFormActivity extends AppCompatActivity {    @OnClick(R.id.btn_1)    void clickOne(){        strObservable1.subscribe(observer);    }    @OnClick(R.id.btn_2)    void clickTwo(){        strObservable2.subscribe(observer);    }    @OnClick(R.id.btn_3)    void clickThree(){        strObservable3.subscribe(subscriber);    }    @OnClick(R.id.btn_4)    void clickFour(){        strObservable4.subscribe(subscriber);    }    @OnClick(R.id.btn_5)    void clickFive(){        Observable.create(new Observable.OnSubscribe<Void>() {            @Override            public void call(Subscriber<? super Void> subscriber) {                startActivity(new Intent(mContext,MainActivity.class));                TernaryFormActivity.this.finish();            }        }).subscribe();    }    Context mContext;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_ternary_form);        mContext = this;        ButterKnife.bind(this);    }    //生产部分1,发送一条内容    public Observable<String> strObservable1 = Observable.create(new Observable.OnSubscribe<String>() {        @Override        public void call(Subscriber<? super String> subscriber) {            subscriber.onNext("人之初");            subscriber.onCompleted();        }    });    //生产部分2发送多条内容    public Observable<String> strObservable2 = Observable.create(new Observable.OnSubscribe<String>() {        @Override        public void call(Subscriber<? super String> subscriber) {            subscriber.onNext("人之初");            subscriber.onNext("性本善");            subscriber.onNext("性相近");            subscriber.onNext("习相远");            subscriber.onCompleted();        }    });    //生产部分3  使用just发送多条内容    public Observable<String> strObservable3 = Observable.just("人之初","性本善","性相近","习相远");    //生产部分4  使用from和数组发送多条内容    String[] threeWordJing = {"人之初","性本善","性相近","习相远"};    public Observable<String> strObservable4 = Observable.from(threeWordJing);    //消费部分    private Subscriber subscriber = new Subscriber<String>() {        @Override        public void onCompleted() {            Toast.makeText(mContext,"结束",Toast.LENGTH_SHORT).show();        }        @Override        public void onError(Throwable e) {            Toast.makeText(mContext,"数据异常",Toast.LENGTH_SHORT).show();        }        @Override        public void onNext(String o) {            Toast.makeText(mContext,o,Toast.LENGTH_SHORT).show();        }    };    //另一种消费部分    private Observer observer = new Observer<String>() {        @Override        public void onCompleted() {            Toast.makeText(mContext,"结束",Toast.LENGTH_SHORT).show();        }        @Override        public void onError(Throwable e) {        }        @Override        public void onNext(String o) {            Toast.makeText(mContext,o,Toast.LENGTH_SHORT).show();        }    };}

很遗憾,目前为止还是没感觉到RxJava有什么特别的屌用.....


第二部分  多线程

        下班回家做饭,炒完菜再蒸米饭和蒸完米饭再开始炒菜都是不合理的。我们可以适当的将蒸米和炒菜分开来,以减少开饭前的用时(有个妹子帮你做菜就更好了,首先得有个妹子……)。这一部分说一下怎么把米饭和炒菜不串联起来。

        假设蒸米饭需要5秒,炒菜要3秒,那么串起来的话Activity就ANR饿死了;

        把米饭扔到子线程,主线程做菜,然后剩下的两秒两个人坐在一起夸夸手艺,调调情(啪!说的跟特么有女朋友似的)然后米饭熟了开饭。

        按照前一部分的套路,我们这样写蒸饭:      

        算了,直接上整个的activity代码吧,多写点注释就好了:

package com.shareye.rxtestbydemo;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.Toast;import java.util.concurrent.TimeUnit;import butterknife.Bind;import butterknife.ButterKnife;import rx.Observable;import rx.Observer;import rx.Subscriber;import rx.android.schedulers.AndroidSchedulers;import rx.schedulers.Schedulers;/** * Created by ShuaiZhang on 2016/7/25. */public class MultiThreadActivity extends AppCompatActivity {    long timeStar = 0;//记录做饭开始时间    long timeStop = 0;//记录做饭结束时间    boolean start = false;//是否开始做饭的标记,防止重复计时    boolean rice = false;//true表示米饭做熟,false表示在做或者未开始    boolean cai = false;//同上    @Bind(R.id.btn_cai)Button btnCai;//模拟做菜的按钮    @Bind(R.id.btn_rice)Button btnRice;//假装它就是蒸米饭    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_multi_thread);        ButterKnife.bind(this);        //点击后模拟炒菜        btnCai.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Toast.makeText(MultiThreadActivity.this, "炒菜开始",Toast.LENGTH_SHORT).show();                if (!start)                    timeStar = System.currentTimeMillis();//记录开始时间                start = true;                Observable.just("炒菜")//套路的第一段                        .subscribeOn(Schedulers.io())//将生产过程“炒菜”放进子线程                        .delay(3, TimeUnit.SECONDS)//假装是炒菜用掉了3秒,到底是哪个线程,我现在说不准                        .observeOn(AndroidSchedulers.mainThread())////将消费的过程指定到主线程                        .subscribe(new Subscriber<String>() {//第二和第三段式                            @Override                            public void onCompleted() {                                Log.i("ASDFGHJKL","cai");                            }                            @Override                            public void onError(Throwable e) {                                Log.i("ASDFGHJKL","exceptionC");                            }                            @Override                            public void onNext(String aVoid) {                                cai = true;//表示炒完菜                                Toast.makeText(MultiThreadActivity.this, aVoid+"结束",Toast.LENGTH_SHORT).show();//提示一下                                stopTime();//结算                            }                        });            }        });        //点击后模拟蒸米饭        btnRice.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Toast.makeText(MultiThreadActivity.this, "米饭开始",Toast.LENGTH_SHORT).show();                if (!start)//只会开始计时一次                    timeStar = System.currentTimeMillis();//记录开始时间                start = true;                Observable.just("蒸米饭")                        .subscribeOn(Schedulers.io())//将生产过程“蒸米饭”放进子线程                        .delay(5,TimeUnit.SECONDS)//假装是生产延续了5秒,到底是哪个线程,我现在说不准                        .observeOn(AndroidSchedulers.mainThread())//将消费的过程指定到主线程                        .subscribe(new Observer<String>() {//第二和第三段式                            @Override                            public void onCompleted() {                                Log.i("ASDFGHJKL","mifan");                            }                            @Override                            public void onError(Throwable e) {                                Log.i("ASDFGHJKL","exceptionM");                            }                            @Override                            public void onNext(String integer) {                                rice = true;//表示米饭已熟                                Toast.makeText(MultiThreadActivity.this, integer + "结束",Toast.LENGTH_SHORT).show();                                stopTime();//结算                            }                        });            }        });    }    //对做饭整个事件做判断    private void stopTime(){        if (rice && cai){//菜和米都做好才能开饭,才具有统计意义            timeStop = System.currentTimeMillis();//获取结束时间            calculate();//处理结果        }    }    //计算并显示结果    private void calculate() {        long result = timeStop - timeStar;//时间差,毫秒值        Toast.makeText(this, "用时:" + result/1000 + "秒",Toast.LENGTH_SHORT).show();        start = rice = cai = false;//标志重置    }}

        对于Rxjava对多线程的使用,主要是两个方法:

        subscribeOn()指定生产过程的发生地;

        observerOn()指定了消费过程的发生地,对于它俩谁先谁后指定,没啥区别。

        对于线程的参数解释,我直接截图了,如下:

截图自:扔物线博客

不很清晰?再来一个:


截图自:来源

 

第三部分   其他操作符

        呵呵,记得文章的开头吗?

        待续吧......下载demo地址


        有下一篇了:Rxjava(三)简单常用操作符






0 0