【问题标题】:Flutter Nested Stream builder -- last stream is getting null before showing dataFlutter Nested Stream builder——最后一个流在显示数据之前为空
【发布时间】:2019-10-01 19:01:08
【问题描述】:

我正在尝试制作一个需要嵌套流构建器的应用程序。 Stream 构建器看起来像这样。但是小部件是在加载最后一个流之前构建的,所以我在调用 getter null 时出错,

StreamBuilder(
  stream: some_stream,
  builder: (context, data){
      return StreamBuilder(
         stream: some_stream,
         builder: (context, data){
             return StreamBuilder(
                stream: some_stream,
                builder: (context, data){

                    return someWidget;

              }

            );
          }
        );
       }
    );

【问题讨论】:

标签: firebase flutter google-cloud-firestore stream-builder


【解决方案1】:

您应该始终使用 StreamBuilder 的结构,例如,

StreamBuilder(
  stream: some_stream,
  builder: (context, data){
      return StreamBuilder(
         stream: some_stream2,
         builder: (context, data){
             if(data.hasError) {
               return Text("Error Occured!!");
             } else if(data.hasData) {
               return StreamBuilder(
                      stream: some_stream,
                      builder: (context, data){
                         if (data.hasError){
                            return Text("Error Occured!!");
                         } else if (data.hasData) {
                            return someWidget;
                         }else {
                            return CircularProgressIndicator();
                         }
                      }
               );
             } else {
               return CircularProgressIndicator();
             }
          }
        );
       }
    );

这将使您在大多数情况下避免出错。

【讨论】:

    【解决方案2】:

    StreamBuilder.builder 完全有可能在 Stream 没有数据、尚未连接到 Stream 或值为 null 时被调用。

    您有责任确保处理所有这些情况。

    要确保初始值永远不会是null,您可以设置inialData

    Future<String> someFutureString = Future.value('initial data seeded');
    
    new StreamBuilder<String>(
      initialData: await someFutureString,
      builder: (ctx, snapshot) { /* ... */ }
    );
    

    虽然这是不好的做法。最好构建这样的构建器,考虑它所使用的快照的状态。构建小部件树应该很快。想象一下,必须等待 3 秒才能到达 initialData。您的小部件树构建将在第一个 await 处被阻止。

    import 'package:flutter/material.dart';
    import 'package:flutter_test/flutter_test.dart';
    
    wrapInMaterialApp(Widget widget) => MaterialApp(
          home: widget,
        );
    
    main() {
      testWidgets('can await initial data', (WidgetTester tester) async {
        final initialData = Future<String>.value('initial value');
        final stream = Stream.fromIterable(['first']);
        final sb = StreamBuilder<String>(
          initialData: await initialData,
          builder: (ctx, snapshot) {
            return Text('${snapshot.data}');
          },
        );
        await tester.pumpWidget(wrapInMaterialApp(sb));
        // Verify that initial data is present
        expect(find.text('initial value'), findsOneWidget);
      });
    
      testWidgets('can return subtree if there is data', (WidgetTester tester) async {
        final stream = Stream.fromIterable(['first']);
        final sb = StreamBuilder<String>(
          stream: stream,
          builder: (ctx, snapshot) {
            if (snapshot.hasData) {
              return Text('${snapshot.data}');
            } else
              return Container();
          },
        );
        var wrappedWidget = wrapInMaterialApp(sb);
        await tester.pumpWidget(wrappedWidget);
    
        expect(find.byType(Container), findsOneWidget);
        expect(find.text('first'), findsNothing);
    
        await tester.pump();
    
        expect(find.byType(Container), findsNothing);
        expect(find.text('first'), findsOneWidget);
      });
    }
    

    ConnectionState 可以帮助您确定构建器应返回的 Widget,可通过 snapshot.connectionState 访问。

    干杯!

    【讨论】:

      猜你喜欢
      • 2020-11-04
      • 1970-01-01
      • 2021-09-17
      • 1970-01-01
      • 2020-06-07
      • 2012-07-28
      • 1970-01-01
      • 1970-01-01
      • 2021-02-18
      相关资源
      最近更新 更多