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

如何在GraphQLClient中调用Hive并通过GetIt正确注册异步实例?

解决GetIt异步注入GraphQLClient(依赖Hive获取Token)的问题

问题背景

需要从Hive中读取sessionToken和authToken并注入到GraphQLClient,但使用GetIt依赖注入时遇到两类错误:

  1. 初始注册Future<GraphQLClient>类型,导致系统找不到GraphQLClient实例
  2. 改用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 17:43:13