Skip to content
No description, website, or topics provided.
Dart Swift Kotlin Objective-C
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
android
ios
lib
test
.gitignore
.metadata
README.md
pubspec.lock
pubspec.yaml

README.md

Flutter中StreamBuilder的用法

先大概说说Stream的概念,这个Stream就是类似平常大家用的比较多的RxJava、RxSwift等框架的思路,它是一个异步数据的源,它可以接受任何数据,通过StreamController可以给这个Stream添加数据,如果这个Stream有监听者就会接收到数据。 代码如下:

import 'dart:async';

void main() {
  // 初始化一个Stream controller
  final StreamController ctrl = StreamController();
  // 添加一个监听
  ctrl.stream.listen((data) => print('$data'));
  // 往Stream中添加数据
  ctrl.sink.add('这个是字符串'); //字符串类型
  ctrl.sink.add(1234);//int 类型
  ctrl.sink.add({'name': '姓名', 'content': 'json对象也行'});//对象类型
  ctrl.sink.add(123.45); //double类型
  // StreamController用完后需要释放
  ctrl.close();
}

StreamBuilder

以前我就经常说Flutter有各种个样的Widget,只有你想不到的。所以既然有Stream,就有对应的Widget,叫StreamBuilder。它本身是一个Widget,然后会监听一个Stream,只要这个Stream有数据变化,它内部的UI就会根据这个新的数据进行变化,完全不需要setState((){})

这里我就拿平常很常见的一个例子来看看这个StreamBuilder怎么用的:发送验证码的按钮 倒计时.2019-07-19 11_14_57-w410

首先建一个类处理倒计时的业务,这个有点类似BLoC模式,将UI和业务逻辑分离。

class CountTime {
  StreamController<int> _controller;
  final int maxSecond;
  CountTime({this.maxSecond = 60}){
    _controller = StreamController();
  }
  ///
  ///提供一个stream
  ///
  Stream<int> get countTimeStream => _controller.stream;
  ///
  /// 开始倒计时
  ///
  startCount() async {
    if (maxSecond <= 0) {
      return;
    }
    for(var i = maxSecond; i >= 0; i--){
      Duration duration;
      if (i == maxSecond) {
        duration = Duration(seconds: 0);
      }else {
        duration = Duration(seconds: 1);
      }
      await Future.delayed(duration, (){
        return i
      }).then((s){
        _controller.sink.add(s);
      });
    }
  }
  dispose() {
    _controller.close();
  }
}

这个业务逻辑类里面就是定义了一个StreamController,控制倒计时的输出,它提供一个countTimeStream供外部调用。 这时候在界面UI上,我们使用StreamBuilder监听这个Stream:

 @override
  void initState() {
  //初始化业务类
    _countTime = CountTime(maxSecond: 60);
    super.initState();
  }
  @override
  void dispose() {
  //销毁
    _countTime.dispose();
    super.dispose();
  }
  
...

StreamBuilder(
    //监听的Stream
    stream: _countTime.countTimeStream,
    //初始化值
    initialData: 0,
    //根据Stream变化进行修改的UI
    builder: (context, snap) {
      var buttonText;
      if (snap.data == 0) {
        onclick = (){
          _countTime.startCount();
        };
        buttonText = '发送验证码';
      }else {
        onclick = null;
        buttonText = '${snap.data} 秒后可以再次发送';
      }
      return FlatButton(
        onPressed: onclick,
        child: Text(buttonText),
        color: Colors.lightBlue,
        textColor: Colors.white,
        disabledColor: Colors.grey,
        disabledTextColor: Colors.white30,
      );
    }
)

这个倒计时按钮就完成了。

You can’t perform that action at this time.