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(三)简单常用操作符
- RxJava(二)歪论
- RxJava教程(二)
- RxJava要素(二)
- RxJava实例(二)
- RxJava学习(二)
- RxJava上手(二)
- RxJava 2.0(二)
- RxJava学习历程(二)
- RxJava 学习笔记(二)
- Rxjava源码(二)-----变换
- RxJava使用入门(二)
- RxJava理解系列(二)
- RxJava学习详解(二)
- 源码阅读--RxJava(二)
- Rxjava------轻松理解(二)
- Android RxJava使用介绍(二) RxJava的操作符
- Android RxJava使用介绍(二) RxJava的操作符
- Android RxJava使用介绍(二) RxJava的操作符
- leetcode 345. Reverse Vowels of a String
- CentOS 安装配置python Sphinx
- swift使用cocoapods导入oc三方库
- select2学习
- Android AudioRecorder录制mp3文件 RAW转MP3
- RxJava(二)歪论
- final关键字
- iOS开发Xcode的图片管理(Images.xcassets)
- iOS中NSString类型数据保留两位小数
- Revit二次开发手记【1】
- leetcode题集——trapping-rain-water
- android 虚拟键适配PopupWindow显示位置
- OSG RTT 渲染到纹理
- 安装配置Zookeeper