首页 > 解决方案 > Flutter Nested Stream builder——最后一个流在显示数据之前为空

问题描述

我正在尝试制作一个需要嵌套流构建器的应用程序。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;

              }

            );
          }
        );
       }
    );

标签: firebasefluttergoogle-cloud-firestorestream-builder

解决方案


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

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

要确保初始值是 never 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);
  });
}

其他可以帮助您确定您的构建器应该返回什么 Widget 的东西,可以ConnectionState通过snapshot.connectionState.

干杯!


推荐阅读