首页 > 解决方案 > Flutter/Firestore/Provider - 瞬间显示错误然后显示流,如何在启动时加载流值?

问题描述

我正在使用 Stream Provider 访问 Firestore 数据并将其传递给我的应用程序。当我第一次运行应用程序时,我面临的问题就开始了。一切都正常开始,但是当我导航到在列表视图中使用 Stream 值的屏幕时,我最初在 UI 重建之前收到错误,并且列表项会在一瞬间出现。这是我得到的错误:

════════ Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building OurInboxPage(dirty, dependencies: [_InheritedProviderScope<List<InboxItem>>]):
The getter 'length' was called on null.
Receiver: null
Tried calling: length

我猜这与访问值并将它们添加到屏幕的加载时间有关吗?如何在应用程序启动时加载所有流值以避免这种情况?

这是我的流代码:

  Stream<List<InboxItem>> get inboxitems {
    return orderCollection
        .where("sendTo", isEqualTo: FirebaseAuth.instance.currentUser.email)
        .snapshots()
        .map(
          (QuerySnapshot querySnapshot) => querySnapshot.docs
              .map(
                (document) => InboxItem.fromFirestore(document),
              )
              .toList(),
        );
  }

然后我将其添加到我的提供者列表中:

   void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  runApp(
    MultiProvider(
      providers: [
        StreamProvider<List<InboxItem>>.value(value: OurDatabase().inboxitems),
      ],
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<OurUser>(
      builder: (_, user, __) {
        return MaterialApp(
          title: 'My App',
          theme: OurTheme().buildTheme(),
          home: HomepageNavigator(),
        );
      },
    );
  }
}

最后是我要显示流项目的页面:

    class OurInboxPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    List<InboxItem> inboxList = Provider.of<List<InboxItem>>(context);
    return Scaffold(
      body: Center(
        child: ListView.builder(
          itemCount: inboxList.length,
          itemBuilder: (context, index) {
            final InboxItem document = inboxList[index];
            return Card(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text(document.event),
                  Icon(Icons.arrow_forward_ios)
                ],
              ),
            );
          },
        ),
      ),
    );
  }
}

谢谢

标签: firebaseflutterdartgoogle-cloud-firestoreprovider

解决方案


是的,它试图在填充数据之前构建,因此出现空错误。

如果没有数据,请将您的包装ListView.builder在 a中并让它显示加载指示器。StreamBuilder

StreamBuilder<List<InboxItem>>(
      stream: // your stream here
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return // your ListView here
        } else {
          return CircularProgressIndicator();
        }
      },
    );

推荐阅读