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

Flutter Web无需自定义类解析JSON响应及API调用报错排查

Flutter Web对接带Firebase鉴权的非Firebase API问题解决及数据展示

1. 先搞定XMLHttpRequest错误(核心是CORS跨域问题)

Postman能正常调用但Flutter Web不行,本质是浏览器的同源策略限制——浏览器会拦截跨域请求,除非后端明确允许你的前端域名访问。

后端需要配置CORS规则,至少要做到:

  • 允许你Flutter Web运行的域名(比如本地开发的http://localhost:5000,线上部署的实际域名)
  • 允许携带Authorization请求头(因为Firebase鉴权Token是放在这个头里的)
  • 开放你需要的请求方法(GET/POST等)

举个Node.js/Express后端的配置示例:

const cors = require('cors');
// 替换成你的前端实际地址
const allowedOrigin = 'http://localhost:5000';

app.use(cors({
  origin: allowedOrigin,
  allowedHeaders: ['Authorization', 'Content-Type'],
  methods: ['GET', 'POST']
}));

2. 正确的Dio调用代码(带Firebase鉴权)

先获取Firebase用户的ID Token,再用Dio发送请求,直接提取响应里的message字段:

import 'package:dio/dio.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'dart:convert'; // 如果后端返回纯文本才需要,默认JSON可省略

Future<String> getDashboardMessage() async {
  // 先确认用户已登录
  final user = FirebaseAuth.instance.currentUser;
  if (user == null) throw Exception('请先登录');

  // 获取Firebase ID Token
  final idToken = await user.getIdToken();

  final dio = Dio();
  try {
    final response = await dio.get(
      'https://your-backend-api.com/dashboard', // 替换成你的API地址
      options: Options(
        headers: {
          'Authorization': 'Bearer $idToken', // 和Postman里的请求头一致
          'Content-Type': 'application/json',
        },
      ),
    );

    if (response.statusCode == 200) {
      // 直接从响应数据里取message,不用自定义类
      // 如果后端返回的是纯文本,就用jsonDecode(response.data)转成Map
      return response.data['message'] ?? '暂无内容';
    } else {
      throw Exception('请求失败,状态码: ${response.statusCode}');
    }
  } catch (e) {
    throw Exception('请求出错: $e');
  }
}

3. 在UI里展示响应内容

用FutureBuilder处理异步请求,覆盖加载、错误、成功三种状态:

import 'package:flutter/material.dart';

class DashboardPage extends StatelessWidget {
  const DashboardPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('我的仪表盘')),
      body: Center(
        child: FutureBuilder<String>(
          future: getDashboardMessage(),
          builder: (context, snapshot) {
            switch (snapshot.connectionState) {
              case ConnectionState.waiting:
                return const CircularProgressIndicator(); // 加载中
              case ConnectionState.done:
                if (snapshot.hasError) {
                  return Text('加载失败: ${snapshot.error}', style: const TextStyle(color: Colors.red));
                } else if (snapshot.hasData) {
                  return Text(snapshot.data!, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w500));
                }
              default:
                return const Text('暂无数据');
            }
          },
        ),
      ),
    );
  }
}

4. 额外排查点

  • 如果提取数据时还是报错:检查后端返回的Content-Type是否为application/json,如果是纯文本,要先用jsonDecode(response.data)转成Map再取值
  • 验证Firebase Token有效性:可以用Firebase官方的Token验证工具确认Token是否合法
  • 确保Dio是最新稳定版:避免版本兼容性问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 23:10:45