1.前言
閱讀本文需要對Rxjava瞭解,如果還沒有了解或者使用過Rxjava的兄die們,可以觀看我另外一篇 Android Rxjava:不一樣的詮釋進行學習。
Rxjava背壓
:被觀察者傳送事件的速度大於觀察者接收事件的速度時,觀察者內會建立一個無限制大少的緩衝池儲存未接收的事件,因此當儲存的事件越來越多時就會導致OOM的出現。(注:當subscribeOn與observeOn不為同一個執行緒時,被觀察者與觀察者記憶體在不同時長耗時任務,就會使傳送與接收速度存在差異。)
背壓例子
public void backpressureSample(){
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
int i = 0;
while(true){
Thread.sleep(500);
i++;
e.onNext(i);
Log.i(TAG,"每500ms傳送一次資料:"+i);
}
}
}).subscribeOn(Schedulers.newThread())//使被觀察者存在獨立的執行緒執行
.observeOn(Schedulers.newThread())//使觀察者存在獨立的執行緒執行
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Thread.sleep(5000);
Log.e(TAG,"每5000m接收一次資料:"+integer);
}
});
}
複製程式碼
例子執行效果
通過上述例子可以大概瞭解背壓是如何產生,因此Rxjava2.0版本提供了 Flowable 解決背壓問題。
本文章就是使用與分析 Flowable 是如何解決背壓問題。
文章中例項 linhaojian的Github
2.目錄
3.簡介
4.使用與原理詳解
4.1 Flowable 與 Observable 的區別
上圖可以很清楚看出二者的區別,其實Flowable
出來以上的區別之外,它其他所有使用與Observable完全一樣。
Flowable
的create例子
public void flowable(){
Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> e) throws Exception {
for(int j = 0;j<=150;j++){
e.onNext(j);
Log.i(TAG," 傳送資料:"+j);
try{
Thread.sleep(50);
}catch (Exception ex){
}
}
}
},BackpressureStrategy.ERROR)
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.newThread())
.subscribe(new Subscriber<Integer>() {
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE); //觀察者設定接收事件的數量,如果不設定接收不到事件
}
@Override
public void onNext(Integer integer) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG,"onNext : "+(integer));
}
@Override
public void onError(Throwable t) {
Log.e(TAG,"onError : "+t.toString());
}
@Override
public void onComplete() {
Log.e(TAG,"onComplete");
}
});
}
複製程式碼
4.2 BackpressureStrategy媒體類
從Flowable原始碼檢視,快取池預設大少為:128
public abstract class Flowable<T> implements Publisher<T> {
/** The default buffer size. */
static final int BUFFER_SIZE;
static {
BUFFER_SIZE = Math.max(1, Integer.getInteger("rx2.buffer-size", 128));
}
.....
}
複製程式碼
通過上面的例子,我們可以看到create方法中的包含了一個BackpressureStrategy媒體類,其包含5種型別:
4.2.1. ERROR
把上面例子改為ERROR型別,執行結果如下:
總結 :當被觀察者傳送事件大於128時,觀察者丟擲異常並終止接收事件,但不會影響被觀察者繼續傳送事件。
4.2.2. BUFFER
把上面例子改為BUFFER型別,執行結果如下:
總結 :與Observable一樣存在背壓問題,但是接收效能比Observable低,因為BUFFER型別通過BufferAsyncEmitter新增了額外的邏輯處理,再傳送至觀察者。
4.2.3. DROP
把上面例子改為DROP型別,執行結果如下:
總結 :每當觀察者接收128事件之後,就會丟棄部分事件。
4.2.4. LATEST
把上面例子改為LATEST型別,執行結果如下:
總結 :LATEST與DROP使用效果一樣,但LATEST會保證能接收最後一個事件,而DROP則不會保證。
4.2.5. MISSING
把上面例子改為MISSING型別,執行結果如下:
總結 :MISSING就是沒有采取背壓策略的型別,效果跟Obserable一樣。
在設定MISSING型別時,可以配合onBackPressure相關操作符使用,也可以到達上述其他型別的處理效果。
4.3 onBackPressure相關操作符
使用例子:
Flowable.interval(50,TimeUnit.MILLISECONDS)
.onBackpressureDrop()//效果與Drop型別一樣
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.newThread())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG,"onNext : "+(aLong));
}
});
複製程式碼
onBackpressureBuffer :與BUFFER型別一樣效果。
onBackpressureDrop :與DROP型別一樣效果。
onBackpressureLaster :與LASTER型別一樣效果。
4.4 request()
4.4.1 request(int count):設定接收事件的數量.
例子:
Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> e) throws Exception {
for(int j = 0;j<50;j++){
e.onNext(j);
Log.i(TAG," 傳送資料:"+j);
try{
Thread.sleep(50);
}catch (Exception ex){
}
}
}
},BackpressureStrategy.BUFFER)
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.newThread())
.subscribe(new Subscriber<Integer>() {
@Override
public void onSubscribe(Subscription s) {
s.request(10); //觀察者設定接收事件的數量,如果不設定接收不到事件
}
@Override
public void onNext(Integer integer) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG,"onNext : "+(integer));
}
@Override
public void onError(Throwable t) {
Log.e(TAG,"onError : "+t.toString());
}
@Override
public void onComplete() {
Log.e(TAG,"onComplete");
}
});
複製程式碼
4.4.2 request擴充套件使用
request還可進行擴充套件使用,當遇到在接收事件時想追加接收數量(如:通訊資料通過幾次接收,驗證準確性的應用場景),可以通過以下方式進行擴充套件:
Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> e) throws Exception {
for(int j = 0;j<50;j++){
e.onNext(j);
Log.i(TAG," 傳送資料:"+j);
try{
Thread.sleep(50);
}catch (Exception ex){
}
}
}
},BackpressureStrategy.BUFFER)
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.newThread())
.subscribe(new Subscriber<Integer>() {
private Subscription subscription;
@Override
public void onSubscribe(Subscription s) {
subscription = s;
s.request(10); //觀察者設定接收事件的數量,如果不設定接收不到事件
}
@Override
public void onNext(Integer integer) {
if(integer==5){
subscription.request(3);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG,"onNext : "+(integer));
}
@Override
public void onError(Throwable t) {
Log.e(TAG,"onError : "+t.toString());
}
@Override
public void onComplete() {
Log.e(TAG,"onComplete");
}
});
複製程式碼
總結:可以動態設定觀察者接收事件的數量,但不影響被觀察者繼續傳送事件。
4.5 requested
requested 與 request不是同一的函式,但它們都是屬於FlowableEmitter類裡的方法,那麼requested()是有什麼作用呢,看看以下例子:
Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> e) throws Exception {
for(int j = 0;j<15;j++){
e.onNext(j);
Log.i(TAG,e.requested()+" 傳送資料:"+j);
try{
Thread.sleep(50);
}catch (Exception ex){
}
}
}
},BackpressureStrategy.BUFFER)
// .subscribeOn(Schedulers.newThread())
// .observeOn(Schedulers.newThread())
.subscribe(new Subscriber<Integer>() {
private Subscription subscription;
@Override
public void onSubscribe(Subscription s) {
subscription = s;
s.request(10); //觀察者設定接收事件的數量,如果不設定接收不到事件
}
@Override
public void onNext(Integer integer) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG,"onNext : "+(integer));
}
@Override
public void onError(Throwable t) {
Log.e(TAG,"onError : "+t.toString());
}
@Override
public void onComplete() {
Log.e(TAG,"onComplete");
}
});
複製程式碼
從圖中我們可以發現,requested列印的結果就是 剩餘可接收的數量 ,它的作用就是可以檢測剩餘可接收的事件數量。
5.總結
到此,Flowable
講解完畢。
如果喜歡我的分享,可以點選 關注 或者 喜歡,你們支援是我分享的最大動力 。