RxDart——Dart和Flutter中的響應式編程入門

RxDart

今年年初開始嘗試使用Flutter開發android APP,期間遇到了很多的坑,但總算是有驚無險。而在作Android原生開發時,RxAndroid讓代碼爽到飛起。爲了找回那種熟悉的感受,特地將RxDart引入到項目中。首先介紹一下RxDart是什麼: RxDart基於ReactiveX,由Dart標準庫中Stream擴展而成,是一個爲Dart語言提供響應式編程的庫。react

如何使用

添加依賴

首先在pubspec.yaml中添加依賴:android

dependencies:
  rxdart: ^0.22.1+1
複製代碼

範例

接下來咱們經過一段代碼來看一下如何使用RxDart編程

Observable.just(1).listen(print);
>>>1
複製代碼

一行完事兒?這都是什麼啊?彆着急,這只是Dart語法的特性,接下來咱們將上面的代碼進行拆分:

//建立一個被觀察者
var observable = Observable.just(1);
//建立一個觀察者
var observa = (int num) {
    print(num);
};
//經過listen實現訂閱
observable.listen(observa);
複製代碼

這下就明朗了,做爲一個Android開發者,對這段代碼充滿親切感。簡直和RxJava一抹同樣!!!數組

建立被觀察者

RxDart提供了不少方法供咱們建立Observable,除了上文中的直接使用just工廠函數從單個值中建立,還有如下幾種建立方法:bash

  • 從一個Stream中建立:Observable(Stream.fromIterable([1, 2, 3, 4, 5])).listen(print);
  • 建立週期性事件:Observable.periodic(Duration(seconds: 1), (x) => x.toString()).listen(print);這段代碼每隔一秒鐘打印一個整數並加一
  • 從Future中建立:經過一個Future建立的Observable,會先等待Future執行完畢,完後發射數據,這個輸出數據就是Future的執行結果,若是Future沒有任何返回值,那麼輸出null。還能夠toStream方法將Future轉換爲Stream而後再建立:
Observable.periodic(Duration(seconds: 1), (x) => x.toString()).listen(print);
Future<String> asyncFunction() async {
    return Future.delayed(const Duration(seconds: 10), () => "十秒後的數據");
}
Observable.fromFuture(asyncFunction()).listen(print);
複製代碼

代碼輸出以下:async

操做符和數據變換

Rx最爽的是什麼?固然是無處不在的操做符啦!我我的以爲操做符是Rx的靈魂,關於操做符原理你們能夠閱讀從源碼查看RxJava中的map和flatMap的用法和區別去了解。下面咱們經過幾個經常使用的操做符學習一下RxDart的操做符使用方法:編輯器

過濾操做符

過濾操做符就是用來過濾掉Observable發射的一些數據,丟棄這些數據只保留過濾後的數據。函數

where

點了半天編輯器老是不自動補全Filterpost

居然沒有Filter操做符號了,還好有個where 咱們實現一個對奇偶進行過濾的操做:

Observable(Stream.fromIterable([1, 2, 3, 4, 5]))
      .where((num) => num % 2 == 0)
      .listen(print);
>>>2 4
複製代碼
skip

若是咱們想跳過前三個數字,咱們可使用skip操做符:學習

Observable(Stream.fromIterable([1, 2, 3, 4, 5]))
      .skip(3)
      .listen(print);
>>> 4 5
複製代碼
take

和skip操做相反,若是咱們去掉後面三個數據,只輸出前面兩個數據:

Observable(Stream.fromIterable([1, 2, 3, 4, 5]))
      .take(2)
      .listen(print);
<<<1 2
複製代碼
distinct

若是咱們要過濾掉原始數據裏重複的項:

Observable(Stream.fromIterable([1, 2, 2, 2, 3, 3, 4, 5]))
      .distinctUnique()
      .listen(print);
>>> 1 2 3 4 5
複製代碼

變換操做符

過濾操做符就是用來過變換Observable發射的一些數據或者Observable自己,將被變換的對象轉換成爲咱們想要的。

map

首先說一下map,依舊是實現一個基本的數據轉換,將數字翻倍:

Observable(Stream.fromIterable([1, 2, 3, 4, 5]))
    .map((num) => num * 2)
    .listen(print);
<<<2 4 6 8 10
複製代碼
flatMap

接下來講一下flatMap,取出一個由數組組成的數組中的元素:

var list1 = [1, 2, 3];
var list2 = [4, 5, 6];
var list3 = [7, 8, 9];
var listAll = [list1, list2, list3];
Observable(Stream.fromIterable(listAll))
    .flatMap((listItem) => Observable(Stream.fromIterable(listItem)))
    .listen(print);
<<<1 2 3 4 5 6 7 8 9
複製代碼
concatMap

相似flatMap操做符,區別在於concatMap按次序鏈接而不是合併那些生成的Observables,而後產生本身的數據序列。 看看下面的代碼:

var list1 = [1, 2, 3];
  var list2 = [4, 5, 6];
  var list3 = [7, 8, 9];
  var listAll = [list1, list2, list3];
  var changeConcatMap = (List<int> listItem) {
    print("concatMap開始變換了");
    return Observable(Stream.fromIterable(listItem));
  };
  var changeFlatMap = (List<int> listItem) {
    print("FlatMap開始變換了");
    return Observable(Stream.fromIterable(listItem));
  };
  Observable(Stream.fromIterable(listAll))
      .concatMap((listItem) => changeConcatMap(listItem))
      .listen(print);
  Observable(Stream.fromIterable(listAll))
      .flatMap((listItem) => changeFlatMap(listItem))
      .listen(print);
複製代碼

輸出結果爲:

結合操做符

startWith

在數據序列的開頭插入一條指定的項:

var observable = Observable(Stream.fromIterable([1, 2, 3, 4, 5]));
observable.startWith(9).listen(print);
>>>9 1 2 3 4 5
複製代碼
merge

使用Merge操做符你能夠將多個Observables的輸出合併,就好像它們是一個單個的Observable同樣。可是可能會讓合併的Observables發射的數據交錯

Observable.merge([
    Stream.fromIterable([1, 2]),
    Stream.fromIterable([3, 4])
  ]).listen(print);
>>> 1 3 2 4
複製代碼
combineLatest

當兩個Observables中的任何一個發射了數據時,使用一個函數結合每一個Observable發射的最近數據項,而且基於這個函數的結果發射數據。

var observable1 = Observable.just(1);
var observable2 = Observable.just(2);
Observable.combineLatest([observable1, observable2], (num) => num)
      .listen(print);
>>>[1,2]
複製代碼
mergeWith

mergeWith將多個被觀察者發射的流合併成一個流。數據按照被髮送的順序傳遞

var observable1 = Observable.just(1);
  var observable2 = Observable.just(5);
  var observable = Observable(Stream.fromIterable([1, 2, 3, 4, 5]));
  observable
      .mergeWith([observable2,observable1])
      .listen(print);
>>> 1 5 1 2 3 4 5
複製代碼

結語

這只是一片RxDart使用的入門教程的。本文並未深刻探討RxDart的實現原理和邏輯,由於這些原理基本和RxJava中的相似。感興趣的能夠去關注個人RxJava系列的文章

相關文章
相關標籤/搜索