如何在GraphQLClient中调用Hive并通过GetIt正确注册异步实例?
解决GetIt异步注入GraphQLClient(依赖Hive获取Token)的问题
问题背景
需要从Hive中读取sessionToken和authToken并注入到GraphQLClient,但使用GetIt依赖注入时遇到两类错误:
- 初始注册
Future<GraphQLClient>类型,导致系统找不到GraphQLClient实例 - 改用
lazySingletonAsync后,即使调用了await sl.allReady(),仍提示实例未就绪
错误分析
第一个错误原因
注册的类型是Future<GraphQLClient>,但代码中尝试获取的是GraphQLClient类型,类型不匹配导致GetIt无法定位对应实例。
第二个错误原因
使用lazySingletonAsync注册异步依赖后,不能用同步的sl.get<GraphQLClient>()获取实例,必须使用异步的sl.getAsync<GraphQLClient>()。此外需确认sl.allReady()确实等待了所有异步服务初始化完成。
正确实现步骤
1. 修正GraphQLClientGenerator的Token读取逻辑
确保从Hive正确读取所需token(根据实际存储结构调整):
class GraphQLClientGenerator { GraphQLClientGenerator(); Future<GraphQLClient> getClient() async { final authUserBox = await Hive.openLazyBox('authUserBox'); final authData = await authUserBox.getAt(0); // 从存储对象中提取token,替换为实际字段名 final sessionToken = authData?['session_token'] ?? ''; final authToken = authData?['auth_token'] ?? ''; final HttpLink httpLink = HttpLink( 'https://xxx/graphqlmf?session_token=$sessionToken', ); final AuthLink authLink = AuthLink( getToken: () async => authToken, ); final Link link = authLink.concat(httpLink); return GraphQLClient(link: link, cache: GraphQLCache()); } }
2. 正确注册异步依赖
在initAuthServiceLocator中使用lazySingletonAsync完成注册:
Future<void> initAuthServiceLocator( GetIt sl, { bool isUnitTest = false, }) async { if (!isUnitTest) { await Hive.initFlutter(); // 提前打开Hive box,避免在getClient中重复操作 await Hive.openLazyBox('authUserBox'); } // 注册异步GraphQLClient sl.lazySingletonAsync<GraphQLClient>( () => GraphQLClientGenerator().getClient(), // 可选:设置实例名,多实例场景下使用 // instanceName: 'mainGraphQLClient', ); // 其他服务注册逻辑... }
3. 确保main函数等待所有服务就绪
GetIt sl = GetIt.instance; void main() async { WidgetsFlutterBinding.ensureInitialized(); // 确保Flutter核心绑定初始化 await initAuthServiceLocator(sl); await sl.allReady(); // 等待所有异步注册的服务完成初始化 runApp(const MyApp()); }
4. 正确获取GraphQLClient实例
在需要使用的场景中,必须通过异步方式获取:
// 在StatefulWidget的initState中使用 @override void initState() { super.initState(); _initGraphQLClient(); } Future<void> _initGraphQLClient() async { final client = await sl.getAsync<GraphQLClient>(); // 使用client执行GraphQL请求 } // 在Bloc/ViewModel中使用 class DataBloc extends Bloc<DataEvent, DataState> { DataBloc() : super(DataInitial()) { on<FetchData>(_onFetchData); } Future<void> _onFetchData(FetchData event, Emitter<DataState> emit) async { final client = await sl.getAsync<GraphQLClient>(); final result = await client.query(...); // 处理请求结果 } }
额外注意事项
如果需要在Widget树中直接使用,建议用FutureBuilder包裹等待实例就绪:
FutureBuilder<GraphQLClient>( future: sl.getAsync<GraphQLClient>(), builder: (context, snapshot) { if (snapshot.hasData) { return GraphQLContentWidget(client: snapshot.data!); } else if (snapshot.hasError) { return Text('初始化失败: ${snapshot.error}'); } else { return const CircularProgressIndicator(); } }, )
内容的提问来源于stack exchange,提问作者John Joe
相关产品推荐
相关产品推荐

