线程切换操作符, 是RxJava不可获取的操作符。
1.subscribeOn
用于给上游配置异步线程,即使给上游分配多次,只会在第一次切换,后面的不切换了。
2. observeOn
用于给下游配置异步线程,给下游分配多次,每次都会切换。以最后一次为准。
3. 线程类型
Schedulers.io(): 代表io流操作,网络操作,文件流等耗时操作。 里面其实就是一个线程池。
Schedulers.newThread:类似new Thread().start(). 用的比较少。没有RXJava加持
Schedulers.computation: 代表CPU大量计算所需要的线程。
AndroidSchedulers.mainThread():专门为android主线程量身定做。
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
Log.d("", "上游subscribe:" + Thread.currentThread().getId());
}
})
//指定上游线程类型
.subscribeOn(Schedulers.io()) //给上游配置异步线程,即使给上游分配多次,只会在第一次切换,后面的不切换了。
.subscribeOn(AndroidSchedulers.mainThread())//被忽略
.subscribeOn(AndroidSchedulers.mainThread())//被忽略
//结果是:Schedulers.io(), 异步线程
//指定下游线程类型
.observeOn(AndroidSchedulers.mainThread())//给下游配置异步线程,给下游分配多次,每次都会切换。以最后一次为准。
.observeOn(Schedulers.io())
.observeOn(Schedulers.io())
//结果是:Schedulers.io(), 异步线程
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
}
});
在默认情况下,是主线程。所以结果是上游发送一次,下游就接到一次,然后上游才能发送下一次。这是一个同步的过程。
//默认情况下。上游发送一次,下游就接到一次,然后上游才能发送下一次。这是一个同步的过程。
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
Log.d("", "subscribe: 上游发送一次 1");
emitter.onNext(1);
Log.d("", "subscribe: 上游发送一次 2");
emitter.onNext(2);
Log.d("", "subscribe: 上游发送一次 3");
emitter.onNext(3);
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d("", "subscribe: 下游接收到" + integer);
}
});
在配置了异步以后。上游和下游各自执行自己的业务。上游可能连续输出三次,下游才接到第一次事件。
//配置了异步以后。
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
Log.d("", "subscribe: 上游发送一次 1");
emitter.onNext(1);
Log.d("", "subscribe: 上游发送一次 2");
emitter.onNext(2);
Log.d("", "subscribe: 上游发送一次 3");
emitter.onNext(3);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d("", "subscribe: 下游接收到" + integer);
}
});
}
下面举一个实际使用的例子,用URL下载图片:
传统的模式是下面这样的:
public void onClick7(View view) {
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("正在下载中。。。");
progressDialog.show();
new Thread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL("http://cms-bucket.ws.126.net/2020/0308/f26c2480j00q6ujvz000yc000hi00b1c.jpg");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(5000);
int responseCode = urlConnection.getResponseCode();
if (responseCode == HTTP_OK) {
Bitmap bitmap = BitmapFactory.decodeStream(urlConnection.getInputStream());
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setTextSize(30);
Bitmap bitmapSuccess = drawTextToBitmap(bitmap, "hello 大家好", paint,60,60);
Message message = handler.obtainMessage();
message.obj = bitmap;
handler.sendMessage(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
Bitmap bitmap = (Bitmap) msg.obj;
imageView.setImageBitmap(bitmap);
if (progressDialog != null) {
progressDialog.dismiss();
}
return false;
}
});
用RxJava如下:
第一转换操作符map,用于下载网络图片,相当于string转bitmap.
第二转换操作符map,用于给下载的图片,添加水印。
第三转换操作符map,用于缓存图片。
以上三个操作符,后面两个可以可以根据需求自由拆卸。每一个map都是一个链条或者卡片。当不需要添加水印的时候,把转水印的操作符去掉就可以了。
public void onClick8(View view) {
Observable.just("http://cms-bucket.ws.126.net/2020/0308/f26c2480j00q6ujvz000yc000hi00b1c.jpg")
//根据url下载图片,相当于把string转成Bitmap
.map(new Function<String, Bitmap>() {
@Override
public Bitmap apply(String s) throws Exception {
URL url = new URL(s);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(5000);
int responseCode = urlConnection.getResponseCode();
if (responseCode == HTTP_OK) {
Bitmap bitmap = BitmapFactory.decodeStream(urlConnection.getInputStream());
return bitmap;
}
return null;
}
})
//给上游的Bitmap添加水印,再发给下游
.map(new Function<Bitmap, Bitmap>() {
@Override
public Bitmap apply(Bitmap bitmap) throws Exception {
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setTextSize(30);
Bitmap bitmapSuccess = drawTextToBitmap(bitmap, "hello 大家好", paint,60,60);
return bitmapSuccess;
}
})
//再给bitmap做个缓存
.map(new Function<Bitmap, Bitmap>() {
@Override
public Bitmap apply(Bitmap bitmap) throws Exception {
//缓存一下
return bitmap;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Bitmap>() {
@Override
public void onSubscribe(Disposable d) {
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setMessage("正在下载中。。。");
progressDialog.show();
}
@Override
public void onNext(Bitmap bitmap) {
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
}
}
@Override
public void onError(Throwable e) {
imageView.setImageDrawable(R.drawable.error);
}
@Override
public void onComplete() {
if (progressDialog != null) {
progressDialog.dismiss();
}
}
});
}
RxJava, 链式或者卡片式编程的好处,就是可以根据需求自由拆卸链条或者卡片。