使用GetX从自定义API获取分类数据失败,请求排查问题
解决GetX获取API分类数据失败问题
问题分析
核心问题包括:
- 控制器数据未用GetX响应式包装,视图无法监听更新
- 视图未触发数据请求,也未监听加载状态与数据变化
- 模型构造函数参数设置不合理,易引发解析异常
- ListView缺少必要的数据源配置
修复步骤
1. 修正模型文件 Category.dart
将Data类默认构造函数参数改为可选,避免API字段缺失或解析时出错:
class Category { List<Data>? data; Category({this.data}); // 改为可选参数 Category.fromJson(Map<String, dynamic> json) { if (json['data'] != null) { data = <Data>[]; json['data'].forEach((v) { data!.add(Data.fromJson(v)); }); } } Map<String, dynamic> toJson() { final Map<String, dynamic> data = <String, dynamic>{}; if (this.data != null) { data['data'] = this.data!.map((v) => v.toJson()).toList(); } return data; } } class Data { int? id; String? image; String? categoryName; String? categoryDes; int? activation; String? createdAt; String? updatedAt; // 所有参数改为可选 Data({this.id, this.image, this.categoryName, this.categoryDes, this.activation, this.createdAt, this.updatedAt}); Data.fromJson(Map<String, dynamic> json) { id = json['id']; image = json['image']; categoryName = json['category_name']; categoryDes = json['category_des']; activation = json['activation']; createdAt = json['created_at']; updatedAt = json['updated_at']; } Map<String, dynamic> toJson() { final Map<String, dynamic> data = <String, dynamic>{}; data['id'] = id; data['image'] = image; data['category_name'] = categoryName; data['category_des'] = categoryDes; data['activation'] = activation; data['created_at'] = createdAt; data['updated_at'] = updatedAt; return data; } }
2. 修复控制器文件 CategoryController.dart
用GetX响应式变量存储数据,初始化时自动请求数据:
import 'dart:convert'; import 'package:get/get.dart'; import 'package:we_serve/models/Category.dart'; import 'package:http/http.dart' as http; class CategoryController extends GetxController{ final isLoading = false.obs; final _category = Rx<Category?>(null); // 响应式可空对象 Category? get category => _category.value; // 暴露getter @override void onInit() { super.onInit(); fetchData(); // 初始化自动请求数据 } fetchData() async { try{ isLoading(true); final response = await http.get(Uri.parse('http://127.0.0.1:8000/api/category')); if(response.statusCode == 200){ final result = jsonDecode(response.body); _category.value = Category.fromJson(result); // 更新响应式变量 }else{ print("HTTP请求失败:状态码${response.statusCode}"); } }catch(e){ print("数据获取异常:$e"); }finally{ isLoading(false); } } }
3. 更新视图文件 Category_slider.dart
用Obx监听状态变化,配置ListView并显示分类数据:
import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:we_serve/controllers/CategoryController.dart'; import '../models/Category.dart'; class CategorySlider extends StatelessWidget { final CategoryController categoryController = Get.put(CategoryController()); @override Widget build(BuildContext context) { return Obx(() { if(categoryController.isLoading.value){ return const Center(child: CircularProgressIndicator()); } final categories = categoryController.category?.data ?? []; return ListView.builder( scrollDirection: Axis.horizontal, shrinkWrap: true, padding: const EdgeInsets.only(right: 8), itemCount: categories.length, itemBuilder: (BuildContext context, int index) { final category = categories[index]; return Container( child: Center( child: Column( children: <Widget>[ Padding( padding: const EdgeInsets.all(10.0), child: Container( width: 200, height: 120, child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), side: const BorderSide(color: Color(0xFF1818B4)))), onPressed: () {}, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ Text( category.categoryName ?? "未命名分类", style: const TextStyle(color: Colors.black), ), ], ), ), ), ), ], ), ), ); }, ); }); } }
额外注意事项
- 模拟器/真机网络适配:Android模拟器需将
127.0.0.1替换为10.0.2.2,iOS模拟器可直接使用127.0.0.1 - 网络权限配置:Android在
AndroidManifest.xml添加<uses-permission android:name="android.permission.INTERNET"/>;iOS在Info.plist配置App Transport Security例外
内容的提问来源于stack exchange,提问作者MUHTASIM JEET
相关产品推荐
相关产品推荐

