在多个页面中使用streamBuilder访问firestore流不起作用

问题描述 投票:0回答:1

这是一个简化的情况:在我的appPage 中,我将profilePage 和dashboardPage 作为页面的主体,并且它们位于索引堆栈中。 这个appPage有一个底部导航栏来控制渲染哪个主体。

假设 profilePage 和dashboardPage 两个主体都具有完全相同的代码,并且正在使用streamBuilder 监听相同的流。 我正在使用提供程序从 firestore 访问我的数据流。

我的问题是只有一个页面可以正确访问数据。 另一个只会显示加载图标,这是在连接状态等待时发生的。 如果我完全删除其中一个页面上的streamBuilder代码并将其替换为空白页面,那么该应用程序将按预期工作。 问题是当尝试在多个页面上使用 StreamBuilder 时。

似乎同一个流不能在不同页面上的 2 个不同的 StreamBuilder 中使用,但我不明白为什么它不起作用,因为我试图将我的流与提供者集中在一起。

我经常使用人工智能来尝试解决这个问题,但无济于事。 我是一名 16 岁的孩子,正在尝试学习编码,非常感谢任何帮助!

这是我的不同页面的代码: 主要:

import 'package:flutter/material.dart';

import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
import 'package:firebase_auth/firebase_auth.dart';

import 'package:provider/provider.dart';
import 'Services/ProviderClass.dart';

import 'pages/landing_page.dart';
import 'pages/login_page.dart';
import 'pages/signup_page.dart';
import 'pages/app_page.dart';


void main() async{
  WidgetsFlutterBinding.ensureInitialized();
    await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform,);

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        Provider<FirestoreService>(
          create: (_) => FirestoreService(),
        )
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        initialRoute: '/AppPage',
        onGenerateRoute: (settings){
          if (FirebaseAuth.instance.currentUser == null && settings.name != '/LoginPage' && settings.name != '/SignupPage'&& settings.name!='/LandingPage') {
          return MaterialPageRoute(builder: (context) => LandingPage());
        }
          switch (settings.name) {
          case '/LandingPage':
            return MaterialPageRoute(builder: (context) => LandingPage());
          case '/LoginPage':
            return MaterialPageRoute(builder: (context) => LoginPage());
          case '/SignupPage':
            return MaterialPageRoute(builder: (context) => SignupPage());
          case '/AppPage':
            return MaterialPageRoute(builder: (context) => AppPage());
          default:
            return MaterialPageRoute(builder: (context) => LoginPage());
        }
        },
      ),
    );
  }
}

应用程序页面代码(底部导航栏包含正文的页面)

import 'package:flutter/material.dart';
import 'AppPages/profile_page.dart';
import 'AppPages/dashboard_page.dart';

class AppPage extends StatefulWidget {
  const AppPage({super.key});

  @override
  State<AppPage> createState() => _AppPageState();
}

class _AppPageState extends State<AppPage> {

  int selectedIndex=1;

  void navigateToIndex(int index){
    setState(() {
      selectedIndex=index;
    });
  }

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.green.shade200, 
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.dashboard),
            label: "Dashboard"
            ),
          BottomNavigationBarItem(
            icon: Icon(Icons.account_circle_sharp),
            label: "Profile"
          )
        ],
        currentIndex: selectedIndex,
        onTap: navigateToIndex,
        fixedColor: Colors.black,
        backgroundColor: Colors.green.shade50,
        type: BottomNavigationBarType.fixed,
        
      ),
      body: IndexedStack(
        index: selectedIndex,
        children: [
          DashboardPage(),
          ProfilePage(),
        ],
      ),
    );
  }
}

仪表板页面

import 'package:flutter/material.dart';

import 'package:cloud_firestore/cloud_firestore.dart';

import 'package:provider/provider.dart';
import '../../Services/ProviderClass.dart';

class DashboardPage extends StatefulWidget {
  const DashboardPage({super.key});

  @override
  State<DashboardPage> createState() => _DashboardPageState();
}

class _DashboardPageState extends State<DashboardPage> {

  late FirestoreService firestoreService;

  @override
  void initState() {
    super.initState();
    firestoreService = Provider.of<FirestoreService>(context, listen: false);
  }

  // This widget is the root of your application
  @override
  Widget build(BuildContext context) {
    var screenSize = MediaQuery.of(context).size;

    return SingleChildScrollView(
            child: Center(
              child: Column(
                children: [

                  SizedBox(height:screenSize.height*0.01,),


                  Text(
                    'Your Nutrition History',
                    style: TextStyle(
                      color: Colors.black,
                      fontSize: 14+screenSize.width*0.03
                      ),
                    ),

                  SizedBox(height:screenSize.height*0.025,),

                  StreamBuilder<DocumentSnapshot>(
                    stream: firestoreService.userStream,
                    builder: (context, snapshot){
                      if (snapshot.connectionState == ConnectionState.waiting) {
                        return Center(child: CircularProgressIndicator());
                      }
                      if (snapshot.hasError) {
                        return Center(child: Text('Error: ${snapshot.error}'));
                      }
                      if (!snapshot.hasData || !snapshot.data!.exists) {
                        return Center(child: Text('No data available'));
                      }
                      //process user data here and return widget based on it
                    }
                  ),

                  SizedBox(height: screenSize.height*0.05,),
                ],
              ),
            ),
          );
        }
  }

个人资料页面

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../../Services/ProviderClass.dart';

class ProfilePage extends StatefulWidget {
  const ProfilePage({super.key});

  @override
  State<ProfilePage> createState() => _ProfilePageState();
}

class _ProfilePageState extends State<ProfilePage> {
  // This widget is the root of your application.
  late FirestoreService firestoreService;

  @override
  void initState() {
    super.initState();
    firestoreService = Provider.of<FirestoreService>(context, listen: false);
  }

  @override
  Widget build(BuildContext context) {
    
    var screenSize = MediaQuery.of(context).size;
    var aspectRatio = screenSize.width/screenSize.height;
    
    return Center(
      child: SingleChildScrollView(
        child: Column(
          children: [
            Text(
              "Profile",
              style: TextStyle(
                color: Colors.black,
                fontSize: 14+ screenSize.width*0.01
              ),
            ),

            StreamBuilder<DocumentSnapshot>(
                    stream: firestoreService.userStream,
                    builder: (context, snapshot){
                      if (snapshot.connectionState == ConnectionState.waiting) {
                        return Center(child: CircularProgressIndicator());
                      }
                      if (snapshot.hasError) {
                        return Center(child: Text('Error: ${snapshot.error}'));
                      }
                      if (!snapshot.hasData || !snapshot.data!.exists) {
                        return Center(child: Text('No data available'));
                      }
                      //process user data here and return widget
                    }
                  ),
          ],
        ),
      ),
    );
  }
}

提供者类

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

class FirestoreService {
  final String userUid = FirebaseAuth.instance.currentUser!.uid;

  Stream<DocumentSnapshot> get userStream {
    return FirebaseFirestore.instance.collection('users').doc(userUid).snapshots();
  }
}

我在同一页面上尝试了 2 个相同的流构建器并且有效,这也让我感到困惑。 当我做 2 个相同的流构建器时,每页一个,只有一个有效。

flutter firebase stream-builder flutter-streambuilder
1个回答
0
投票

唯一需要更改的是提供程序类。 使用流控制器可以将单个流广播给许多听众。

这里应该是新的 Firestore 提供程序代码,其他任何内容都不需要更改

import 'dart:async';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

class FirestoreService {
  final String userUid = FirebaseAuth.instance.currentUser!.uid;
  final StreamController<DocumentSnapshot> userController = StreamController<DocumentSnapshot>.broadcast();

  FirestoreService() {
    FirebaseFirestore.instance.collection('users').doc(userUid).snapshots().listen((snapshot) {
      userController.add(snapshot);
    });
}
© www.soinside.com 2019 - 2024. All rights reserved.