Flutter如何刷新StreamBuilder?

时间:2020-03-13 01:43:30

标签: flutter dart stream listener onchange

考虑以下代码:

StreamBuilder<QuerySnapshot> _createDataStream(){   
    return StreamBuilder<QuerySnapshot>(
          stream: Firestore.instance.collection("data").limit.(_myLimit).snapshots(),
          builder: (context, snapshot){
              return Text(_myLimit.toString);   
            }
        );
}

我希望_myLimit变量更改时StreamBuilder刷新。 可能会这样:

void _incrementLimit(){
    setState(() =>_myLimit++);
}

我的问题是,除了setState((){});之外,还有没有其他更快的方法。 因为当build()变量更改时,我不想重新调用整个_myLimit方法。

我想出了另一种方法,但是我觉得有更好的解决方案,因为我认为我没有使用.periodic功能,并且嵌套了Stream,所以我不确定这是多么平常:

Stream<int> myStream = Stream.periodic(Duration(), (_) => _myLimit);
...
@override
Widget build(BuildContext context){
...
return StreamBuilder<int>(
                    stream: myStream,
                    builder: (context, snapshot){
                      return _createDataStream;
                    },
                  ),
...
}

解决方案

import 'dart:async';
import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new _MyAppState();
  }
}

class _MyAppState extends State<MyApp> {

  int myNum = 0;

  final StreamController _myStreamCtrl = StreamController.broadcast();
  Stream get onVariableChanged => _myStreamCtrl.stream;
  void updateMyUI() => _myStreamCtrl.sink.add(myNum);

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    _myStreamCtrl.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child:
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
            StreamBuilder(
              stream: onVariableChanged,
              builder: (context, snapshot){
                if(snapshot.connectionState == ConnectionState.waiting){
                  updateMyUI();
                  return Text(". . .");
                }
                return Text(snapshot.data.toString());
              },
            ),
            RaisedButton(
              child: Text("Increment"),
              onPressed: (){
                myNum++;
                updateMyUI();
                },
        )
        ],
      ),
    )));
  }
}

其他一些想法,StreamBuilder的外观也是如此:

StreamBuilder(
  stream: onVariableChanged,
  builder: (context, snapshot){
    if(snapshot.connectionState == ConnectionState.waiting){
      return Text(myNum.toString());
    }
    return Text(snapshot.data.toString());
  },
),
StreamBuilder(
  stream: onVariableChanged,
  initialData: myNum,
  builder: (BuildContext context, AsyncSnapshot snapshot){
    if(snapshot.data == null){
      return Text("...");
    }
    return Text(snapshot.data.toString());
  },
),

1 个答案:

答案 0 :(得分:5)

StreamController声明一个broadcast,然后将此Stream的{​​{1}}设置一个友好的名称,然后每次您要重建包装的小部件时( StreamController只需使用StreamBuilder的{​​{1}}属性来sink一个新值,它将触发StreamController

您可以使用addStreamBuilder,而无需设置类型。

但是,如果在键入StreamBuilder时使用AsyncSnapshotStreamBuilder<UserModel>,则会看到AsyncSnapshot<UserModel>中的所有变量和方法。

snapshot.data.

这样,您可以使用UserModelfinal StreamController<UserModel> _currentUserStreamCtrl = StreamController<UserModel>.broadcast(); Stream<UserModel> get onCurrentUserChanged => _currentUserStreamCtrl.stream; void updateCurrentUserUI() => _currentUserStreamCtrl.sink.add(_currentUser); StreamBuilder<UserModel>( stream: onCurrentUserChanged, builder: (BuildContext context, AsyncSnapshot<UserModel> snapshot) { if (snapshot.data != null) { print('build signed screen, logged as: ' + snapshot.data.displayName); return blocs.pageView.pagesView; //pageView containing signed page } print('build login screen'); return LoginPage(); //print('loading'); //return Center(child: CircularProgressIndicator()); }, ) (例如,具有不同颜色的图标)StatelessWidget(用于重建整个页面)。

为了提高性能,流是最好的方法。

编辑: 我正在使用refresh just a single sub-widget方法,因此最好在homePageBloc.dart(具有所有业务逻辑的常规控制器类)中声明变量,并在homePage.dart(具有类)中创建StreamBuilder扩展了无状态/有状态小部件并负责UI)。

编辑:我的without using setState,如果您正在使用Firebase中的Cloud Firestore数据库,则可以使用BLoC architecture代替UserModel.dart

DocumentSnapshot