【Rxjava詳解】(二) 操作符的妙用

文章目錄

    • 接口變化
    • 操作符
      • map
      • flatmap
      • debounce
      • throttleFirst()
      • take
      • concat

RxJava 是一個基于 觀察者模式的異步編程庫,它提供了豐富的操作符來處理和轉換數據流。 操作符是 RxJava 的核心組成部分,它們提供了一種靈活、可組合的方式來處理數據流,使得開發者可以更加便捷地進行數據處理和流程控制。

接口變化

RxJava 2.x擁有了新的特性,其依賴于4個接口:

  • Publisher
  • Subscriber
  • Subscription
  • Processor
  1. SubscriberFunc1變為Function等等。此外,還引入了SingleMaybeCompletable等新的可觀察類型。
  2. RxJava 2.x 中的背壓支持:RxJava 2.x 引入了對背壓的支持,新增了Flowable類型來處理背壓場景。同時,對一些操作符的行為進行了一些修改以適應背壓機制。
  3. 異常處理方式的變化:在RxJava 1.x中,異常處理是通過onError()方法來處理,而在RxJava 2.x中,引入了onError(Throwable)方法和onError(Throwable, boolean)方法,允許開發者控制是否中斷流程。
  4. 取消訂閱的方式變化:在RxJava 1.x中,使用unsubscribe()方法取消訂閱,而在RxJava 2.x中,使用dispose()方法取消訂閱

關于背壓:

在RxJava中,背壓(Backpressure)是一種處理生產者和消費者之間速度不匹配的機制。通過背壓,可以使得消費者根據自身的處理能力告知生產者它們能夠接受的數據量,從而避免生產者產生過多的數據導致消費者無法處理的情況。

而在RxJava 2.x ~ RxJava 3.x,發生以下變化:

  • 不再支持Backpressure:RxJava 3.x不再內置支持背壓機制,而是采用基于Reactive-Streams的響應式規范,并提供了相應的Flowable類型。因此,在RxJava 3.x中,需要使用Flowable來處理背壓場景。
  • Observer接口的變化:在RxJava 3.x中,Observer接口被拆分為兩個接口:ObserverDisposableObserver接口用于處理事件的消費,而Disposable接口用于取消訂閱。
  • SingleObserverCompletableObserver的變化:在RxJava 3.x中,SingleObserverCompletableObserver接口的方法簽名有所變化,取消訂閱的方法從dispose()改為了onDispose()

操作符

RxJava提供了對事件序列進行變換的支持,這是它的核心功能之一.所謂變換,就是將事件序列中的對象或整個序列進行加工處理,轉換成不同的事件或事件序列。
操作符是用來對Observable(或Flowable)流進行轉換、過濾、組合和操作的方法。

RxJava提供了很多很有用的操作符。多的要死
在Rxjava 3.x 下,有以下常見的操作符:

  1. map:將Observable發射的數據項通過指定的函數進行轉換,并發射轉換后的數據項。
  2. filter:根據指定的條件過濾Observable發射的數據項,只發射滿足條件的數據項。
  3. take:只發射Observable發射的前N個數據項,忽略后面的數據項。
  4. skip:跳過Observable發射的前N個數據項,只發射后面的數據項。
  5. merge:將多個Observable合并成一個Observable,按照時間順序發射合并后的數據項。
  6. zip:將多個Observable按照順序進行合并,每個數據項都是由對應位置的Observable發射的數據項組合而成。
  7. concat:按照順序連接多個Observable,依次發射它們的數據項,等前一個Observable完成后才會訂閱下一個Observable。
  8. onErrorResumeNext:在Observable發生錯誤時,使用備用的Observable繼續發射數據項。
  9. retry:在Observable發生錯誤時,進行錯誤重試,重新訂閱Observable。
  10. interval:創建一個按照固定時間間隔發射遞增數值的Observable。
  11. debounce:只有在指定的時間間隔內沒有發射新的數據項時,才發射最后一個數據項。
  12. distinct:過濾掉重復的數據項,只發射不重復的數據項。
  13. flatMap:將Observable發射的數據項轉換為Observable集合,并按順序發射這些Observable發射的數據項。
  14. reduce:對Observable發射的數據項進行累積操作,返回最終的累積結果。
  15. scan:對Observable發射的數據項進行累積操作,并按順序發射每次累積的結果

在此簡單介紹其中幾個的用法:

map

示意圖:

image.png

實際上,map操作符可以理解為對Observable發射的每個數據項都應用一個函數,將原始數據項轉換為另一種形式的數據項,然后再發射出去。(感覺Kotlin里有)

假設我們有一個Observable發射的是整數序列,我們想將每個整數乘以2,并發射出去。

Observable<Integer> observable = Observable.just(1, 2, 3, 4, 5);observable.map(number -> number * 2).subscribe(result -> System.out.println(result));輸出:
2
4
6
8
10

flatmap

flatMap操作符會對Observable的每個數據項應用一個函數,這個函數返回一個新的Observable。然后,它會將這些新的Observable合并成一個Observable,并發射合并后的數據項。

假設我們有一個Observable發射的是字符串數組,我們想將每個字符串拆分為字符數組,并發射出去。

Observable<String> observable = Observable.just("Hello", "World", "RxJava");observable.flatMap(str -> Observable.fromArray(str.split(""))).subscribe(character -> System.out.print(character + " "));

輸出:

H e l l o W o r l d R x J a v a

flatMap操作符將每個字符串拆分為字符數組,并將所有的字符合并成了一個Observable,最終發射出去。

debounce

debounce操作符也是RxJava中常用的操作符之一,它用于在一定時間間隔內只發射最后一個數據項,忽略中間的數據項。debounce操作符主要用于處理需要在一定時間內連續發生的事件,但只關心最后一個事件的場景。

在安卓開發中,debounce操作符可以用于處理用戶輸入場景,比如搜索框輸入關鍵詞時,通常需要等待用戶停止輸入一段時間后再進行搜索,以減少不必要的網絡請求。

Observable<String> observable = Observable.create(emitter -> {editText.addTextChangedListener(new TextWatcher() {@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {}@Overridepublic void afterTextChanged(Editable s) {emitter.onNext(s.toString());}});
});observable.debounce(500, TimeUnit.MILLISECONDS).subscribe(keyword -> {// 進行搜索操作performSearch(keyword);});

我們首先創建了一個Observable對象,該Observable通過監聽EditText的文本變化事件,將用戶輸入的關鍵詞發射出去。

然后,我們使用debounce操作符,設置一個時間間隔(這里是500毫秒),它會在用戶輸入停止500毫秒后才發射最后一個關鍵詞。

最后,通過subscribe方法訂閱Observable,并在訂閱中執行搜索操作。

這樣做的好處是,用戶在連續輸入時,debounce操作符會忽略中間的輸入,只關注最后一個輸入,在用戶停止輸入一段時間后才執行搜索操作,避免不必要的網絡請求。

throttleFirst()

throttleFirst()操作符也是RxJava中常用的操作符之一,它用于在指定時間間隔內只發射第一個數據項,忽略后續的數據項。throttleFirst操作符主要用于處理需要限制觸發頻率的事件,保證在指定時間間隔內只處理一次。

在安卓開發中,throttleFirst操作符可以用于處理按鈕點擊事件,防止用戶重復點擊按鈕造成重復操作:

Observable<Object> observable = Observable.create(emitter -> {button.setOnClickListener(v -> {emitter.onNext(new Object());});
});observable.throttleFirst(1000, TimeUnit.MILLISECONDS).subscribe(event -> {// 執行按鈕點擊操作ClickAction();});

take

take()操作符也是RxJava中常用的操作符之一,用于從Observable中取出一定數量的數據項,并在達到指定數量后停止發射。它可以與Retrofit和RxJava的線程切換一起使用,來控制網絡請求結果的數量和線程切換。

在安卓開發中,通常使用Retrofit進行網絡請求,而結合RxJava可以實現異步操作和線程切換。下面是一個結合Retrofit和RxJava的實例,使用take操作符來限制結果數量,并配合線程切換:

首先,創建一個網絡請求的接口:

public interface ApiInterface {@GET("data")Observable<List<Data>> getData();
}

然后,創建一個Retrofit實例,并結合RxJava的Observable進行網絡請求:

ApiInterface apiInterface = RetrofitClient.getClient().create(ApiInterface.class);apiInterface.getData().subscribeOn(Schedulers.io()) // 在IO線程進行網絡請求.observeOn(AndroidSchedulers.mainThread()) // 在主線程接收和處理結果.take(5) // 只接收前5個數據項.subscribe(dataList -> {// 處理獲取到的數據for (Data data : dataList) {Log.d(TAG, "Received data: " + data.toString());}}, throwable -> {// 處理錯誤Log.e(TAG, "Error: " + throwable.getMessage());});

先建了一個ApiInterface的實例,用于定義網絡接口。

然后用Retrofit和RxJava的Observable結合進行網絡請求。通過subscribeOn()方法指定在IO線程進行網絡請求,observeOn()方法指定在主線程接收和處理結果。使用take(5)操作符來限制只接收前5個數據項,即結果數量限制為5。

最后,通過subscribe方法訂閱Observable,并在訂閱中處理獲取到的數據或錯誤。

concat

concat()操作符是RxJava中常用的操作符之一,用于將多個Observable按順序連接在一起,并依次發射數據。它可以在安卓開發中用于實現多個下載任務的順序執行。

在安卓開發中,有時需要進行多個文件的下載操作,可以使用concat操作符來依次執行下載任務:

創建一個下載任務的接口:

public interface DownloadService {@GETObservable<ResponseBody> downloadFile(@Url String fileUrl);
}

Retrofit結合RxJava的Observable進行下載任務:

DownloadService service = RetrofitClient.getClient().create(DownloadService.class);Observable<ResponseBody> downloadTask1 = service.downloadFile("http://example.com/file1");
Observable<ResponseBody> downloadTask2 = service.downloadFile("http://example.com/file2");
Observable<ResponseBody> downloadTask3 = service.downloadFile("http://example.com/file3");Observable.concat(downloadTask1, downloadTask2, downloadTask3).subscribeOn(Schedulers.io()) // 在IO線程進行下載任務.observeOn(AndroidSchedulers.mainThread()) // 在主線程接收和處理結果.subscribe(responseBody -> {// 處理下載完成的文件saveFile(responseBody);}, throwable -> {// 處理錯誤Log.e(TAG, "Error: " + throwable.getMessage());});

操作符真的很多,其他的可以看詳細文檔進行轉換,學習RxJava的操作符的關鍵是理解其原理和使用場景,以及熟悉常用的操作符和它們的功能。

操作符可以總結為以下幾種:

  1. 轉換操作符:用來對數據進行轉換,比如將一個數據類型轉換成另一個數據類型,或者對數據進行映射或扁平化處理。
  2. 過濾操作符:用來過濾數據流中的元素,比如只保留滿足特定條件的元素,或者去除重復的元素。
  3. 組合操作符:用來將多個數據流進行組合,比如將多個流依次連接在一起,或者合并多個流的元素。
  4. 錯誤處理操作符:用來處理異常和錯誤情況,比如在遇到錯誤時返回一個默認值,或者在錯誤發生時切換到另一個數據流。
  5. 調度操作符:用來控制數據流在不同線程之間的切換,比如將數據流切換到IO線程執行耗時操作,或者將結果切換回主線程更新UI。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/161961.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/161961.shtml
英文地址,請注明出處:http://en.pswp.cn/news/161961.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++二分算法:得到子序列的最少操作次數

本文涉及的基礎知識點 二分查找算法合集 題目 給你一個數組 target &#xff0c;包含若干 互不相同 的整數&#xff0c;以及另一個整數數組 arr &#xff0c;arr 可能 包含重復元素。 每一次操作中&#xff0c;你可以在 arr 的任意位置插入任一整數。比方說&#xff0c;如果…

【如何學習Python自動化測試】—— 多層窗口定位

6 、 多層窗口定位 多層窗口指的是在操作系統圖形界面中&#xff0c;一個窗口被另一個窗口覆蓋的情況。在多層窗口中&#xff0c;如何定位需要操作的窗口&#xff1f; 一種常見的方法是使用操作系統提供的AltTab快捷鍵&#xff0c;可以在打開的所有窗口中快速切換焦點。如果需要…

第十三章 控制值的轉換 - 處理UTC時區指示符

文章目錄 第十三章 控制值的轉換 - 處理UTC時區指示符 第十三章 控制值的轉換 - 處理UTC時區指示符 對于支持XML的類&#xff0c;可以指定在從XML文檔導入時是否使用UTC時區指示符。同樣&#xff0c;可以指定是否在導出時包含UTC時區指示符。 為此&#xff0c;指定XMLTIMEZON…

GEE生物量碳儲量——利用sens和MK檢驗方法計算1987-2022年森林地上生物量AGB和碳儲量的時空變化特征

簡介: 本文是將之前已經處理好的森林生物量和碳儲量數據保存到GEE Assets中,然后分別將單張影像導入到代碼編輯器中,構建一個時間序列集合,并且這里需要用到的是我們給影像添加指定的時間屬性,這樣方便進行下一步的時序分析和空間預測。 首先,需要收集1987年至2022年期…

C語言實現Linux下TCP Server測試工具

Linux TCP Server測試工具代碼 實現了接受數據并輸出文本和十六制字符串 #include <stdio.h> #include<string.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <signal.h> #include <arpa/inet.h> #incl…

STM32內存介紹

ROM是一種只讀存儲器&#xff0c;經歷了從NOR Flash到NAND Flash再到現在的eMMC的發展。為了便于使用和大批量生產&#xff0c;ROM進一步分為了4種類型&#xff1a;PROM、EPROM、EEPROM和Flash。PROM只能被編程一次&#xff0c;EPROM可擦寫可編程且可達1000次&#xff0c;EEPRO…

leetcode/hot100

文章目錄 一、哈希1.兩數之和2.字母異位詞分組3.最長連續序列 二、雙指針4. 移動零5.盛最多水的容器6.三數之和7.接雨水 三、滑動窗口8.無重復字符的最長子串9.找到字符串中所有字母異位詞 四、子串10.和為 K 的子數組 一、哈希 1.兩數之和 1. 兩數之和 class Solution { pu…

規則引擎Drools使用,0基礎入門規則引擎Drools(二)高級語法

文章目錄 系列文章索引五、規則屬性1、enabled屬性2、dialect屬性3、salience屬性4、no-loop屬性5、activation-group屬性6、agenda-group屬性7、auto-focus屬性8、timer屬性9、date-effective屬性10、date-expires屬性 六、Drools高級語法1、global全局變量2、query查詢3、fun…

20231122給RK3399的挖掘機開發板適配Android12

20231122給RK3399的挖掘機開發板適配Android12 2023/11/22 9:30 主要步驟&#xff1a; rootrootrootroot-X99-Turbo:~$ tar --use-compress-programpigz -xvpf rk356x_android12_220722.tgz rootrootrootroot-X99-Turbo:~$ cd rk_android12_220722/ rootrootrootroot-X99-Tur…

rk3568 適配以太網(mac 2 mac)

rk3568 適配以太網(mac 2 mac) MDI(Media Dependent Interface)是以太網中的一種接口標準,用于連接物理層(PHY)和數據鏈路層(MAC)之間的傳輸介質。 在以太網中,MDI通常通過RJ-45插座來實現,用于連接網線和網絡設備。MDI接口提供了電氣和機械特性,使得PHY和MAC能夠正…

Python通過串口收發文件

單位內外網是隔離的,USB對拷線被禁用,安全優盤使用太費事,就想到了通過串口傳輸文件. import serial from xmodem import XMODEM import osdef Send_File(filepath, portCOM8, baudrate115200):bn os.path.basename(filepath)filesize os.stat(filepath).st_sizestrSendFile…

帶記憶的超級GPT智能體,能做飯、煮咖啡、整理家務!

隨著AI技術的快速迭代&#xff0c;Alexa、Siri、小度、天貓精靈等語音助手得到了廣泛應用。但在自然語言理解和完成復雜任務方面仍然有限。 相比文本的標準格式&#xff0c;語音充滿復雜性和多樣性&#xff08;例如&#xff0c;地方話&#xff09;,傳統方法很難適應不同用戶的…

【每日OJ —— 20.有效的括號(棧)】

每日OJ —— 20.有效的括號&#xff08;棧&#xff09; 1.題目&#xff1a;20.有效的括號&#xff08;棧&#xff09;2.方法講解2.1.解法2.1.1.算法講解2.1.2.代碼實現2.1.3.提交通過展示 1.題目&#xff1a;20.有效的括號&#xff08;棧&#xff09; 2.方法講解 2.1.解法 利用…

2023 年 亞太賽 APMCM (B題)國際大學生數學建模挑戰賽 |數學建模完整代碼+建模過程全解全析

當大家面臨著復雜的數學建模問題時&#xff0c;你是否曾經感到茫然無措&#xff1f;作為2022年美國大學生數學建模比賽的O獎得主&#xff0c;我為大家提供了一套優秀的解題思路&#xff0c;讓你輕松應對各種難題。 問題一&#xff1a; 建立沒有作物的玻璃溫室內的溫度和風速分…

C語言二十四彈--喝汽水問題

C語言解決喝汽水問題 題目&#xff1a;喝汽水&#xff0c;1瓶汽水1元&#xff0c;2個空瓶可以換一瓶汽水&#xff0c;給20元&#xff0c;可以喝多少汽水&#xff1f; 方法一、逐瓶購買法 思路&#xff1a;一瓶瓶的買 當空瓶有兩個時&#xff0c;汽水數加1即可。 #include &…

MacOS 成為惡意軟件活動的目標

Malwarebytes 警告稱&#xff0c;一個針對 Mac 操作系統 (OS) 的數據竊取程序正在通過虛假的網絡瀏覽器更新分發給毫無戒心的目標。 Atomic Stealer&#xff0c;也稱為 AMOS&#xff0c;是 Mac OS 上流行的竊取程序。 Atomic Stealer (AMOS) 惡意軟件最近被發現使用“ClearFa…

ImportError: cannot import name ‘contextfilter‘ from ‘jinja2‘解決方案

大家好,我是愛編程的喵喵。雙985碩士畢業,現擔任全棧工程師一職,熱衷于將數據思維應用到工作與生活中。從事機器學習以及相關的前后端開發工作。曾在阿里云、科大訊飛、CCF等比賽獲得多次Top名次。現為CSDN博客專家、人工智能領域優質創作者。喜歡通過博客創作的方式對所學的…

匯編-pop出棧指令

32位匯編 執行動作分為兩步&#xff1a; 第一步&#xff1a;讀出數據 第二步&#xff1a;改變棧地址 如果操作數是16位&#xff0c; 則ESP加2&#xff1b; 如果操作數是32位&#xff0c; 則ESP加4 espesp2 或 espesp4 格式&#xff1a;

九、sdl顯示bmp圖片

前言 SDL中內置加載BMP的API&#xff0c;使用起來會更加簡單&#xff0c;便于初學者學習使用SDL 如果需要加載JPG、PNG等其他格式的圖片&#xff0c;可以使用第三方庫&#xff1a;SDL_image 測試環境&#xff1a; ffmpeg的4.3.2自行編譯版本windows環境qt5.12sdl2.0.22&…

力扣第462題 最小操作次數使數組元素相等 II C++ 排序基礎 附Java代碼

題目 462. 最小操作次數使數組元素相等 II 中等 相關標簽 數組 數學 排序 給你一個長度為 n 的整數數組 nums &#xff0c;返回使所有數組元素相等需要的最小操作數。 在一次操作中&#xff0c;你可以使數組中的一個元素加 1 或者減 1 。 示例 1&#xff1a; 輸入&a…