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

Flutter中Get API请求无响应问题排查求助

问题:Flutter调用JSONPlaceholder API无响应,无控制台输出

在Flutter项目中调用JSONPlaceholder的Get接口获取用户数据,该接口在网页和Postman中均能正常返回数据,但代码里完全没响应,控制台也未打印任何调试日志。已通过QuickType生成对应数据模型,多次尝试仍无法解决,请求排查。


相关代码

HomeView代码

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import '../models/userModel.dart';

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

  @override
  State<HomeView> createState() => _HomeViewState();
}

class _HomeViewState extends State<HomeView> {
  // 创建空列表存储用户数据
  List<Users> userDetails = [];

  // 从API获取用户数据的异步方法
  Future<List<Users>> getUsers() async {
    print("api method calling");
    final response =
        await http.get(Uri.parse("https://jsonplaceholder.typicode.com/users"),);
    print('api response check');
    var data = jsonDecode(response.body.toString());
    print('api data received');
    if (response.statusCode == 200) {
      for (Map<String, dynamic> index in data) {
        userDetails.add(Users.fromJson(index));
      }
      return userDetails;
    } else {
      return userDetails;
    }
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
        future: getUsers(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            print('no connection error');
            if (snapshot.hasData) {
              print('snapshot has data');
              return ListView.builder(
                  itemCount: 1,
                  itemBuilder: (context, index) {
                    return Container(
                      margin: const EdgeInsets.all(10),
                      height: 100,
                      color: Colors.greenAccent,
                      padding: const EdgeInsets.symmetric(
                          vertical: 10, horizontal: 20),
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: const [
                          Text('User Id : data'),
                          Text('User Id : data'),
                          Text('User Id : data'),
                          Text('User Id : data'),
                        ],
                      ),
                    );
                  });
            } else {
              print('snapshot has no data');
              return const Center(
                child: CircularProgressIndicator(),
              );
            }
          } else {
            return const Center(
              child: Text("connection error"),
            );
          }
        });
  }
}

数据模型代码

// To parse this JSON data, do
//
//     final users = usersFromJson(jsonString);

import 'dart:convert';

List<Users> usersFromJson(String str) => List<Users>.from(json.decode(str).map((x) => Users.fromJson(x)));

String usersToJson(List<Users> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Users {
  Users({
    required this.id,
    required this.name,
    required this.username,
    required this.email,
    required this.address,
    required this.phone,
    required this.website,
    required this.company,
  });

  int id;
  String name;
  String username;
  String email;
  Address address;
  String phone;
  String website;
  Company company;

  factory Users.fromJson(Map<String, dynamic> json) => Users(
    id: json["id"],
    name: json["name"],
    username: json["username"],
    email: json["email"],
    address: Address.fromJson(json["address"]),
    phone: json["phone"],
    website: json["website"],
    company: Company.fromJson(json["company"]),
  );

  Map<String, dynamic> toJson() => {
    "id": id,
    "name": name,
    "username": username,
    "email": email,
    "address": address.toJson(),
    "phone": phone,
    "website": website,
    "company": company.toJson(),
  };
}

class Address {
  Address({
    required this.street,
    required this.suite,
    required this.city,
    required this.zipcode,
    required this.geo,
  });

  String street;
  String suite;
  String city;
  String zipcode;
  Geo geo;

  factory Address.fromJson(Map<String, dynamic> json) => Address(
    street: json["street"],
    suite: json["suite"],
    city: json["city"],
    zipcode: json["zipcode"],
    geo: Geo.fromJson(json["geo"]),
  );

  Map<String, dynamic> toJson() => {
    "street": street,
    "suite": suite,
    "city": city,
    "zipcode": zipcode,
    "geo": geo.toJson(),
  };
}

class Geo {
  Geo({
    required this.lat,
    required this.lng,
  });

  String lat;
  String lng;

  factory Geo.fromJson(Map<String, dynamic> json) => Geo(
    lat: json["lat"],
    lng: json["lng"],
  );

  Map<String, dynamic> toJson() => {
    "lat": lat,
    "lng": lng,
  };
}

class Company {
  Company({
    required this.name,
    required this.catchPhrase,
    required this.bs,
  });

  String name;
  String catchPhrase;
  String bs;

  factory Company.fromJson(Map<String, dynamic> json) => Company(
    name: json["name"],
    catchPhrase: json["catchPhrase"],
    bs: json["bs"],
  );

  Map<String, dynamic> toJson() => {
    "name": name,
    "catchPhrase": catchPhrase,
    "bs": bs,
  };
}

main.dart代码

import 'package:flutter/material.dart';
import 'package:responsive_login_ui/views/home_view.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(title: Text('User Data From Api'),),
        body:  HomeView()
      ),
    );
  }
}

问题排查与修复方案

1. 核心问题定位

  • FutureBuilder重复发起请求:build方法每次执行都会调用getUsers(),导致多次请求冲突,甚至引发状态异常
  • 无异常捕获机制:getUsers方法未处理网络请求、JSON解析时的异常,一旦出错会静默失败,控制台无日志输出
  • ListView配置错误:itemCount写死为1,无法展示全部数据;UI文本硬编码,未绑定实际接口返回数据
  • 数据模型无空值处理:直接从JSON取字段,若接口返回空值会触发类型转换错误

2. 分步修复

修复1:将Future初始化移至initState

避免重复发起请求,保存Future引用:

class _HomeViewState extends State<HomeView> {
  List<Users> userDetails = [];
  late Future<List<Users>> _usersFuture;

  @override
  void initState() {
    super.initState();
    _usersFuture = getUsers(); // 仅在初始化时发起一次请求
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
        future: _usersFuture, // 使用保存的Future引用
        builder: (context, snapshot) {
          // builder逻辑不变
        });
  }
}

修复2:给getUsers添加异常捕获

添加try-catch块,打印异常信息定位问题:

Future<List<Users>> getUsers() async {
  try {
    print("api method calling");
    final response =
        await http.get(Uri.parse("https://jsonplaceholder.typicode.com/users"));
    print('api response status code: ${response.statusCode}');
    if (response.statusCode == 200) {
      var data = jsonDecode(response.body.toString());
      print('api data received, length: ${data.length}');
      for (Map<String, dynamic> index in data) {
        userDetails.add(Users.fromJson(index));
      }
      return userDetails;
    } else {
      print('api request failed, status code: ${response.statusCode}');
      return userDetails;
    }
  } catch (e) {
    print('api request error: $e');
    return userDetails;
  }
}

修复3:修正ListView配置与数据绑定

使用实际数据长度作为itemCount,并绑定用户数据到UI:

if (snapshot.hasData) {
  print('snapshot has data, length: ${snapshot.data!.length}');
  return ListView.builder(
      itemCount: snapshot.data!.length,
      itemBuilder: (context, index) {
        final user = snapshot.data![index];
        return Container(
          margin: const EdgeInsets.all(10),
          height: 100,
          color: Colors.greenAccent,
          padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text('User Id : ${user.id}'),
              Text('Name : ${user.name}'),
              Text('Email : ${user.email}'),
              Text('Username : ${user.username}'),
            ],
          ),
        );
      });
}

修复4:优化数据模型的空值处理

给模型的fromJson方法添加空值默认值,避免类型错误:

// Users类示例,嵌套类如Address、Geo、Company同理修改
factory Users.fromJson(Map<String, dynamic> json) => Users(
  id: json["id"] ?? 0,
  name: json["name"] ?? "",
  username: json["username"] ?? "",
  email: json["email"] ?? "",
  address: Address.fromJson(json["address"] ?? {}),
  phone: json["phone"] ?? "",
  website: json["website"] ?? "",
  company: Company.fromJson(json["company"] ?? {}),
);

3. 额外检查项

  • 确保Android项目的AndroidManifest.xml中添加了网络权限:<uses-permission android:name="android.permission.INTERNET"/>
  • iOS项目无需额外配置(接口为HTTPS,符合App Transport Security要求)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 17:15:33