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

Flutter技术求助:API返回数据无法渲染到Scaffold容器

问题排查与修复

你的代码存在几个关键问题导致数据无法渲染,逐一说明:

  • 全局parse变量未被赋值:API请求返回的数据从未存入这个变量,parsePinCode里的final parse是局部变量,和全局的parse毫无关联,所以UI始终显示空内容。
  • 未处理异步请求结果:按钮点击时调用getPincode但没加await,无法获取实际返回值,更无法更新到变量中。
  • 未触发UI更新:即使获取到数据,也没调用setState通知Flutter框架重建UI,所以UI不会刷新显示新数据。
  • TextEditingController位置错误:把控制器放在build方法里,每次UI重建都会重新创建,导致输入状态丢失,应该移到State类的成员变量位置。

修改后的完整代码

import 'dart:convert';
import 'package:api/model/pin_code.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  // 存储API返回的邮编数据,初始为空
  List<PinCode> pinCodeData = [];
  // 将控制器移到State成员变量,避免重建丢失状态
  final TextEditingController pinCodeController = TextEditingController();

  Future<List<PinCode>> getPincode(String pincode) async {
    var response = await http
        .get(Uri.parse('https://api.postalpincode.in/pincode/${pincode}'));
    return compute(parsePinCode, response.body);
  }

  List<PinCode> parsePinCode(String responseBody) {
    final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
    return parsed.map<PinCode>((json) => PinCode.fromJson(json)).toList();
  }

  @override
  Widget build(BuildContext context) {
    double height = MediaQuery.of(context).size.height;
    double width = MediaQuery.of(context).size.width;

    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: const Text('Pin code Rest API Demo '),
      ),
      body: Column(
        children: [
          SizedBox(height: height * 0.09),
          TextFormField(
            controller: pinCodeController,
            keyboardType: TextInputType.number,
            decoration: const InputDecoration(
              hintText: '输入邮编',
              border: OutlineInputBorder(),
            ),
          ),
          SizedBox(height: height * 0.05),
          ElevatedButton(
            onPressed: () async {
              if (pinCodeController.text.isEmpty) return;
              // await获取异步结果
              final data = await getPincode(pinCodeController.text);
              // 调用setState更新UI
              setState(() {
                pinCodeData = data;
              });
            },
            child: const Text("Search"),
          ),
          const SizedBox(height: 20),
          Container(
            color: Colors.blue,
            padding: const EdgeInsets.all(16),
            child: pinCodeData.isEmpty
                ? const Text('请输入邮编查询')
                : Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text('状态: ${pinCodeData[0].status}'),
                      Text('邮编: ${pinCodeData[0].postOffice?[0].pincode}'),
                      Text('地区: ${pinCodeData[0].postOffice?[0].name}'),
                      Text('城市: ${pinCodeData[0].postOffice?[0].city}'),
                      Text('州: ${pinCodeData[0].postOffice?[0].state}'),
                    ],
                  ),
          )
        ],
      ),
    );
  }

  @override
  void dispose() {
    // 销毁控制器,避免内存泄漏
    pinCodeController.dispose();
    super.dispose();
  }
}

关键修改点说明

  1. 变量类型修正:把原来的Map parse改成List<PinCode> pinCodeData,因为API返回的是数组结构,和parsePinCode返回的类型一致。
  2. 控制器移到成员变量:避免每次build重建控制器,同时在dispose里销毁它防止内存泄漏。
  3. 异步请求处理:按钮点击时用await获取getPincode的返回值,然后调用setState更新pinCodeData,触发UI重建。
  4. UI内容优化:蓝色容器里根据pinCodeData是否为空显示不同内容,同时展示具体的邮编信息,而不是直接打印对象。
  5. 移除冗余代码:删除parsePinCode里的局部parse变量,因为它没有实际作用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 12:15:48