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

Flutter Secure Storage读取JWT时出现“Unexpected null value.”异常

问题分析与解决方案

你遇到的屏幕闪烁"Unexpected null value."错误,核心原因大概率是异步操作的状态未正确处理,或是API层异常未被完整捕获导致错误短暂暴露在UI上,以下是具体排查和修复方案:

1. UI层异步状态处理(最可能的原因)

如果你的UI直接调用API方法而未用FutureBuilder或类似方式处理异步状态,会导致在readJwt完成前,UI尝试访问未初始化的null值,触发错误后又因异步操作完成更新UI,最终出现错误闪烁的情况。

修复示例:用FutureBuilder包裹API调用

FutureBuilder<ApiResponse<List<TrainingReference>>>(
  future: apiService.getTrainingReferences(),
  builder: (context, snapshot) {
    // 等待异步操作完成时显示加载状态
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const CircularProgressIndicator();
    }
    // 捕获异步操作中的所有异常
    if (snapshot.hasError) {
      return Text('加载失败: ${snapshot.error}');
    }
    // 处理API返回的业务错误
    final response = snapshot.data!;
    if (response.hasError) {
      return Text('业务错误: ${response.error}');
    }
    // 正常渲染数据
    return ListView.builder(
      itemCount: response.body!.length,
      itemBuilder: (context, index) {
        return ListTile(title: Text(response.body![index].name));
      },
    );
  },
)

2. API层异常捕获优化

你当前的readJwt调用在try块外部,若抛出EmptyJwtException会直接传播到UI层,导致未处理的错误提示。需将readJwt移到try块内部,统一捕获所有异常。

修改后的getTrainingReferences方法

Future<ApiResponse<List<TrainingReference>>> getTrainingReferences() async {
  Logger.logApiRequest(_className, _methodGetTrainingReferences, "");
  Uri url = Uri.http(_apiHost, "api/v1/workouts");
  var apiResponse = ApiResponse<List<TrainingReference>>();
  http.Response response;
  
  try {
    // 将readJwt移到try块内,确保异常被捕获
    String jwt = await readJwt(); 
    response = await http.get(
      url,
      headers: {HttpHeaders.authorizationHeader: 'Bearer $jwt'},
    );
    
    if (response.statusCode == 200) {
      apiResponse.body = (json.decode(response.body) as List)
          .map((e) => TrainingReference.fromJson(e))
          .toList();
      Logger.logApiResponse(
          _className, _methodGetTrainingReferences, response.body.toString());
    } else {
      apiResponse.hasError = true;
      apiResponse.error = response.body;
      Logger.logApiNotSuccess(_className, _methodGetTrainingReferences,
          response.statusCode, response.body.toString());
    }
  } catch (e) {
    apiResponse.hasError = true;
    // 区分自定义异常和通用异常
    if (e is EmptyJwtException) {
      apiResponse.error = 'JWT令牌为空,请重新登录';
    } else {
      apiResponse.error = '未知错误: ${e.toString()}';
    }
    Logger.logApiResponse(
        _className, _methodGetTrainingReferences, e.toString());
    // 若无需上层处理异常,可移除rethrow
    // rethrow;
  }
  
  return apiResponse;
}

3. 额外排查点

  • Web端存储验证:在Chrome开发者工具的Application -> Local Storage中,检查是否存在flutter_secure_storage前缀的JWT键值对(插件会自动添加前缀),确认存储内容正常。
  • 非空断言检查:排查UI层和模型解析代码中的!非空断言,替换为null安全处理(比如用??提供默认值,或条件判断确保值非空),避免触发"Unexpected null value."错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 20:35:55