Flutter StreamBuilder使用介紹

StreamBuilder介紹

前面介紹過(guò)FutureBuilder,它是一個(gè)Widget控件寥枝,提供了異步數(shù)據(jù)獲取與ui更新的能力井仰,StreamBuilder與FutureBuilder類似[官方文檔]恶守,也是一個(gè)Widget控件第献,不一樣的是FutureBuilder依靠Future來(lái)做異步數(shù)據(jù)獲取,而StreamBuilder則是依賴Stream來(lái)做異步數(shù)據(jù)獲取兔港。

Stream介紹

在講StreamBuilder前得先介紹下Stream這個(gè)東西庸毫。通俗點(diǎn)講,Stream就是個(gè)事件流衫樊,有點(diǎn)類似于RxJava飒赃,它允許我們從一端發(fā)射一個(gè)事件,從另外一端去監(jiān)聽(tīng)事件的變化科侈,通過(guò)Stream我們可以在Flutter上設(shè)計(jì)出基于事件流驅(qū)動(dòng)的響應(yīng)式代碼邏輯载佳。

Stream的簡(jiǎn)單實(shí)用

事實(shí)上Stream并是不Flutter的產(chǎn)物,而是由Dart提供的兑徘,Stream是一個(gè)抽象的接口刚盈,Dart提供了StreamController接口類可以讓我們方便的使用Stream,步驟大致如下:

  • 創(chuàng)建StreamController
  • 獲取StreamSink用作發(fā)射事件
  • 獲取Stream用作事件的監(jiān)聽(tīng)
  • 獲取StreamSubscription用作管理監(jiān)聽(tīng)挂脑,關(guān)閉暫停等
  StreamSubscription<String> subscription;
  //創(chuàng)建StreamController
  var streamController = StreamController<String>();
  // 獲取StreamSink用于發(fā)射事件
  StreamSink<String> get streamSink  => streamController.sink;
  // 獲取Stream用于監(jiān)聽(tīng)
  Stream<String> get streamData => streamController.stream;

  //監(jiān)聽(tīng)事件
  subscription = streamData.listen((value) {
        // do something
  });

 //發(fā)射一個(gè)事件.
streamSink.add(index.toString());

StreamBuilder的使用介紹

  • 構(gòu)造方法
StreamBuilder({Key key, T initialData, Stream<T> stream, @required AsyncWidgetBuilder<T> builder })

initialData : 默認(rèn)初始化數(shù)據(jù)
stream : stream事件流對(duì)象
builder : 負(fù)責(zé)根據(jù)不同狀態(tài)創(chuàng)建對(duì)應(yīng)ui的方法實(shí)現(xiàn)
AsyncWidgetBuilder前面在講FutureBuilder的時(shí)候已經(jīng)介紹過(guò),這里不再贅述欲侮。

  • 其他方法
    afterConnected:返回一個(gè)AsyncSnapshot崭闲,當(dāng)訂閱了stream時(shí)會(huì)回調(diào)此AsyncSnapshot
    afterData:返回一個(gè)AsyncSnapshot,當(dāng)stream有事件觸發(fā)時(shí)會(huì)回調(diào)此AsyncSnapshot
    afterDisconnected:返回一個(gè)AsyncSnapshot威蕉,當(dāng)取消訂閱stream時(shí)會(huì)回調(diào)此AsyncSnapshot
    afterDone:返回一個(gè)AsyncSnapshot刁俭,當(dāng)stream被關(guān)閉時(shí)會(huì)回調(diào)此AsyncSnapshot
    afterError:返回一個(gè)AsyncSnapshot,stream發(fā)生錯(cuò)誤時(shí)會(huì)回調(diào)此AsyncSnapshot

StreamBuilder 內(nèi)部已經(jīng)幫我們完成了stream的訂閱與取消訂閱韧涨,在initState的時(shí)候進(jìn)行事件的訂閱牍戚,在dispose的時(shí)候進(jìn)行事件的反訂閱侮繁,源碼在_StreamBuilderBaseState里,關(guān)鍵過(guò)程大致如下

void initState() {
    super.initState();
    _summary = widget.initial();
    _subscribe();
  }

void dispose() {
    _unsubscribe();
    super.dispose();
  }
void _subscribe() {
    if (widget.stream != null) {
      _subscription = widget.stream.listen((T data) {
        setState(() {
          _summary = widget.afterData(_summary, data);
        });
      }, onError: (Object error) {
        setState(() {
          _summary = widget.afterError(_summary, error);
        });
      }, onDone: () {
        setState(() {
          _summary = widget.afterDone(_summary);
        });
      });
      _summary = widget.afterConnected(_summary);
    }
  }
  void _unsubscribe() {
    if (_subscription != null) {
      _subscription.cancel();
      _subscription = null;
    }
  }

從上面的源碼里面我們也可以清楚得看見(jiàn)StreamBuilder的各個(gè)回調(diào)方法的調(diào)用過(guò)程如孝。

完整例子

下面給出一個(gè)完整的代碼例子宪哩,我們的頁(yè)面在初始化的時(shí)候創(chuàng)建了StreamController,頁(yè)面上面有個(gè)按鈕第晰,當(dāng)點(diǎn)擊按鈕的時(shí)候就會(huì)發(fā)射出一個(gè)事件锁孟,StreamBuilder訂閱了這個(gè)事件,并且把data打印出來(lái)

import 'dart:async';

import 'package:flutter/material.dart';
import 'dart:io';
import 'dart:convert';

/**
 * Created by nls on 2019/7/20.
 * Nothing.
 */
class StreamBuilderDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(primaryColor: Colors.blue),
      home: HomeWidget());
  }
}

class HomeWidget extends StatefulWidget {
  @override
  State createState() {
    return HomeState();
  }
}

class HomeState extends State<HomeWidget> {
  var index = 0;
  StreamSubscription<String> subscription;
  //創(chuàng)建StreamController
  var streamController;
  // 獲取StreamSink用于發(fā)射事件
  StreamSink<String> get streamSink  => streamController.sink;
  // 獲取Stream用于監(jiān)聽(tīng)
  Stream<String> get streamData => streamController.stream;

  void onFloatActionButtonPress() {
    //發(fā)射一個(gè)事件.
    streamSink.add(index.toString());
    index++;
  }

  @override
  void initState() {
    super.initState();
    streamController = StreamController<String>();
    streamSink.add("0");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text('streamBuilder')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            StreamBuilder<String>(
              stream: streamData,
              builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
                return Text('Result: ${snapshot.data}');
              }
            )
          ],
        )
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: onFloatActionButtonPress,
          child: Icon(Icons.add))
    );
  }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末茁瘦,一起剝皮案震驚了整個(gè)濱河市品抽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌甜熔,老刑警劉巖圆恤,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異腔稀,居然都是意外死亡盆昙,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)烧颖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)弱左,“玉大人,你說(shuō)我怎么就攤上這事炕淮〔鸹穑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵涂圆,是天一觀的道長(zhǎng)们镜。 經(jīng)常有香客問(wèn)我,道長(zhǎng)润歉,這世上最難降的妖魔是什么模狭? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮踩衩,結(jié)果婚禮上嚼鹉,老公的妹妹穿的比我還像新娘。我一直安慰自己驱富,他們只是感情好锚赤,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著褐鸥,像睡著了一般线脚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,792評(píng)論 1 290
  • 那天浑侥,我揣著相機(jī)與錄音姊舵,去河邊找鬼。 笑死寓落,一個(gè)胖子當(dāng)著我的面吹牛括丁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播零如,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼躏将,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了考蕾?” 一聲冷哼從身側(cè)響起祸憋,我...
    開(kāi)封第一講書(shū)人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎肖卧,沒(méi)想到半個(gè)月后蚯窥,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡塞帐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年拦赠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片葵姥。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡荷鼠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出榔幸,到底是詐尸還是另有隱情允乐,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布削咆,位于F島的核電站牍疏,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏拨齐。R本人自食惡果不足惜鳞陨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瞻惋。 院中可真熱鬧厦滤,春花似錦、人聲如沸歼狼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蹂匹。三九已至,卻和暖如春凹蜈,著一層夾襖步出監(jiān)牢的瞬間限寞,已是汗流浹背忍啸。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留履植,地道東北人计雌。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像玫霎,于是被迫代替她去往敵國(guó)和親凿滤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容