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
相关产品推荐
相关产品推荐

