You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter+Bloc模式下Firebase/Firestore连接失败问题求助

Flutter Bloc架构下Cloud Firestore连接失败排查

已完成Firebase所有配置且初始化成功,但调用Cloud Firestore时无法连接后端,以下是相关代码、错误日志及排查修复方案。

相关代码文件

repository.dart

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

class AnswersRepository {
  getAnswers() async {
    FirebaseFirestore.instance.collection("answers").get()
        .then((querySnapshot) {
      for (var result in querySnapshot.docs) {
       return result.data();
        print("SSSSSSSSSSSSSSS ${result.data()}");
      }
    });
  }
}

状态类

class AnswersSuccessState extends AnswersState {
  Map<String, dynamic> answers;
  AnswersSuccessState({required this.answers});
}

Bloc类

class AnswersBloc extends Bloc<AnswersEvent, AnswersState> {
  final AnswersRepository repo;
  AnswersBloc(this.repo) : super(AnswersLoadingState()) {
    on<AnswersEvent>((event, emit) async{
      emit(AnswersLoadingState());
      try {
        final answers = await repo.getAnswers();
        emit(AnswersSuccessState(answers: answers));
      }catch(e) {
        emit(AnswersErrorState(msg: e.toString()));
      }
    });
  }

}

main.dart

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp( MyApp());
}

class MyApp extends StatelessWidget {
  final fb = Firebase.initializeApp();
   MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Quick Answers',
      theme: ThemeData(
        brightness: Brightness.light,
        primaryColor: Colors.deepPurpleAccent,
        fontFamily: 'Georgia',
      ),
      home: Scaffold(
        body: FutureBuilder(
          future: fb,
          builder: (context, snapshot) {
            if(snapshot.hasError) {
              print(snapshot.error);
              return const Center(child: Text("something wrong",
                style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),),);
            } else if (snapshot.hasData) {
              return RepositoryProvider<AnswersRepository>(
                create: (context) => AnswersRepository(),
                child: MultiBlocProvider(
                    providers: [
                      BlocProvider<AnswersBloc>(
                          create: (context)
                          => AnswersBloc(context.read<AnswersRepository>())
                            ..add(FetchAnswers()))
                    ],
                    child: HomeScreen()
                ),
              );
            } else {
              return const Center(child: CircularProgressIndicator(),);
            }
    }),
      )
    );
  }
}

UI代码

child: BlocConsumer<AnswersBloc, AnswersState>( 
        listener: (context, state) {},
        builder: (context, state) {
          if(state is AnswersLoadingState) {
            return const Center(child: CircularProgressIndicator(),);
          } else if(state is AnswersSuccessState) {
            GridView.builder(
                itemCount: 20,
                gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2) ,
                itemBuilder: (context, index) {
                  return CardWidget(
                      color: Colors.lightBlueAccent,
                       title: state.answers[index].title,
                        link: state.answers[index].link,);
                }
            );
          } else if(state is AnswersErrorState) {
            return Center(child: Text(state.msg),);
          }
          return Container();
        } ,
      )

运行错误日志

Launching lib\main.dart on sdk gphone x86 in debug mode...
Running Gradle task 'assembleDebug'...
√  Built build\app\outputs\flutter-apk\app-debug.apk.
Installing build\app\outputs\flutter-apk\app.apk...
Debug service listening on ws://127.0.0.1:55327/MSL098hcqm4=/ws
Syncing files to device sdk gphone x86...
W/DynamiteModule(24240): Local module descriptor class for com.google.android.gms.providerinstaller.dynamite not found.
I/DynamiteModule(24240): Considering local module com.google.android.gms.providerinstaller.dynamite:0 and remote module com.google.android.gms.providerinstaller.dynamite:0
W/ProviderInstaller(24240): Failed to load providerinstaller module: No acceptable module com.google.android.gms.providerinstaller.dynamite found. Local version is 0 and remote version is 0.
I/s.quick_answer(24240): The ClassLoaderContext is a special shared library.
I/s.quick_answer(24240): The ClassLoaderContext is a special shared library.
I/TetheringManager(24240): registerTetheringEventCallback:osama.atraqchi.answers.quick_answers
V/NativeCrypto(24240): Registering com/google/android/gms/org/conscrypt/NativeCrypto's 295 native methods...
W/s.quick_answer(24240): Accessing hidden method Ljava/security/spec/ECParameterSpec;->getCurveName()Ljava/lang/String; (greylist, reflection, allowed)
I/ProviderInstaller(24240): Installed default security provider GmsCore_OpenSSL
W/Firestore(24240): (24.2.2) [OnlineStateTracker]: Could not reach Cloud Firestore backend. Backend didn't respond within 10 seconds
W/Firestore(24240): 
W/Firestore(24240): This typically indicates that your device does not have a healthy Internet connection at the moment. The client will operate in offline mode until it is able to successfully connect to the backend.
W/Firestore(24240): (24.2.2) [WatchStream]: (60a1739) Stream closed with status: Status{code=UNAVAILABLE, description=Channel shutdownNow invoked, cause=null}.
W/DynamiteModule(24240): Local module descriptor class for com.google.android.gms.providerinstaller.dynamite not found.
I/DynamiteModule(24240): Considering local module com.google.android.gms.providerinstaller.dynamite:0 and remote module com.google.android.gms.providerinstaller.dynamite:0
W/ProviderInstaller(24240): Failed to load providerinstaller module: No acceptable module com.google.android.gms.providerinstaller.dynamite found. Local version is 0 and remote version is 0.

排查修复方案

1. 修复repository.dart的异步返回问题

当前getAnswers()无返回值,且使用then时提前return导致仅获取第一个文档,修改后:

class AnswersRepository {
  Future<List<Map<String, dynamic>>> getAnswers() async {
    final querySnapshot = await FirebaseFirestore.instance.collection("answers").get();
    return querySnapshot.docs.map((doc) => doc.data()).toList();
  }
}
  • 明确返回Future<List<Map<String, dynamic>>>,适配UI列表需求
  • 使用await替代then,避免回调嵌套
  • 返回所有文档数据的列表,而非单个文档

2. 调整状态类与Bloc的类型匹配

原状态类的answers字段类型错误,修改为列表类型:

class AnswersSuccessState extends AnswersState {
  final List<Map<String, dynamic>> answers;
  AnswersSuccessState({required this.answers});
}

Bloc中同步调整逻辑,并指定具体事件类型:

class AnswersBloc extends Bloc<AnswersEvent, AnswersState> {
  final AnswersRepository repo;
  AnswersBloc(this.repo) : super(AnswersLoadingState()) {
    on<FetchAnswers>((event, emit) async{
      emit(AnswersLoadingState());
      try {
        final answers = await repo.getAnswers();
        emit(AnswersSuccessState(answers: answers));
      }catch(e) {
        emit(AnswersErrorState(msg: e.toString()));
      }
    });
  }
}

3. 修正UI数据访问逻辑

适配状态类的列表类型,调整数据访问方式:

else if(state is AnswersSuccessState) {
  return GridView.builder(
      itemCount: state.answers.length,
      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2) ,
      itemBuilder: (context, index) {
        final answer = state.answers[index];
        return CardWidget(
            color: Colors.lightBlueAccent,
             title: answer['title'],
              link: answer['link'],);
      }
  );
}

4. 解决Firestore连接问题

除日志提示的网络检查外,还需确认:

  • Firebase控制台中已创建Firestore数据库,调试阶段可临时将规则设为allow read, write: if true;
  • google-services.json已正确放置在android/app目录,包名与Firebase项目一致
  • 测试设备/模拟器网络正常,可切换物理设备验证

内容的提问来源于stack exchange,提问作者Osama Mohammed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 21:09:32