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

Flutter数组格式API响应获取与UI使用方法及Observable模式咨询

Flutter 数组格式API响应处理与登录逻辑修复

一、当前登录代码的核心错误与修复

你的LoginController.login方法返回的是Future<List<UserLogin>>(异步操作),但在LoginPage的按钮点击事件中直接将其强制转换为List<UserLogin>,这会导致运行时错误。同时代码中还有几个逻辑问题:

  • 未处理异步操作的等待过程
  • 使用res != []判断数组非空是错误的,应使用res.isNotEmpty
  • 未处理API请求的异常(如网络错误、状态码非200)

修复后的按钮点击逻辑

onPressed: () async {
  final String email = emailController.text;
  final String pass = pwController.text;

  try {
    // 等待异步请求完成
    List<UserLogin> res = await LoginController.login(email, pass);
    
    if (res.isNotEmpty) {
      print(res[0].role);
      if (res[0].role == 'ADMIN') {
        Navigator.of(context).push(MaterialPageRoute(
          builder: (_) => homePageAdmin()
        ));
      } else {
        Fluttertoast.showToast(
          msg: "用户不存在或权限不足",
          toastLength: Toast.LENGTH_LONG,
          gravity: ToastGravity.CENTER,
          timeInSecForIosWeb: 1,
          backgroundColor: Color.fromARGB(255, 3, 87, 156),
          textColor: Colors.white,
          fontSize: 12.0
        );
      }
    } else {
      Fluttertoast.showToast(
        msg: "登录失败,未获取到用户数据",
        toastLength: Toast.LENGTH_LONG,
        gravity: ToastGravity.CENTER,
        timeInSecForIosWeb: 1,
        backgroundColor: Color.fromARGB(255, 3, 87, 156),
        textColor: Colors.white,
        fontSize: 12.0
      );
    }
  } catch (e) {
    // 捕获请求异常并提示
    Fluttertoast.showToast(
      msg: "登录失败:${e.toString()}",
      toastLength: Toast.LENGTH_LONG,
      gravity: ToastGravity.CENTER,
      timeInSecForIosWeb: 1,
      backgroundColor: Colors.red,
      textColor: Colors.white,
      fontSize: 12.0
    );
  }
}

二、Flutter中获取数组格式API响应并在UI中使用的常用方法

1. Async/Await + setState

适合简单场景,在异步方法中获取数据后调用setState更新UI:

List<UserLogin> userList = [];

void fetchData() async {
  try {
    userList = await LoginController.login(email, pass);
    setState(() {}); // 通知UI更新
  } catch (e) {
    // 处理异常
  }
}

// 在UI中直接使用userList
if (userList.isNotEmpty) {
  Text(userList[0].userName);
}

2. FutureBuilder

Flutter官方提供的组件,自动管理异步操作的加载、成功、失败状态:

// 在State类中定义Future变量
late Future<List<UserLogin>> _futureUserList;

@override
void initState() {
  super.initState();
  // 初始化请求(或在点击登录时赋值)
  _futureUserList = LoginController.login(email, pass);
}

// 在build中使用FutureBuilder
FutureBuilder<List<UserLogin>>(
  future: _futureUserList,
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return CircularProgressIndicator(); // 加载中
    } else if (snapshot.hasError) {
      return Text('请求失败:${snapshot.error}'); // 错误状态
    } else if (snapshot.hasData && snapshot.data!.isNotEmpty) {
      return Text('欢迎 ${snapshot.data![0].userName}'); // 成功状态
    } else {
      return Text('未获取到数据');
    }
  },
)

3. 状态管理库(支持Observable模式)

适合复杂页面或全局状态共享场景,比如使用GetX、Provider等实现Observable模式,自动监听数据变化并更新UI。

三、Observable模式的使用建议

可以使用Observable模式来管理登录状态,以下是GetX实现的示例:

1. 添加GetX依赖

在pubspec.yaml中添加:

dependencies:
  get: ^4.6.5

2. 创建Observable状态控制器

import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:AtDocHUB/Model/User.dart';

class LoginStateController extends GetxController {
  // 用RxList实现Observable数组
  RxList<UserLogin> userList = <UserLogin>[].obs;
  RxBool isLoading = false.obs;
  RxString errorMsg = ''.obs;

  Future<void> login(String email, String password) async {
    isLoading.value = true;
    errorMsg.value = '';
    try {
      final response = await http.get(Uri.parse(
          'http://192.168.0.111:8081/AtdochubJ-3/user/login?useremail=$email&userpassword=$password'));
      
      if (response.statusCode == 200) {
        final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
        userList.value = parsed.map<UserLogin>((json) => UserLogin.fromJson(json)).toList();
        
        if (userList.isNotEmpty && userList[0].role == 'ADMIN') {
          Get.to(() => homePageAdmin());
        } else {
          errorMsg.value = "用户不存在或权限不足";
        }
      } else {
        throw Exception('请求失败,状态码:${response.statusCode}');
      }
    } catch (e) {
      errorMsg.value = "登录失败:${e.toString()}";
    } finally {
      isLoading.value = false;
    }
  }
}

3. 在LoginPage中使用Observable状态

// 在MyCustomFormState中初始化控制器
final LoginStateController loginController = Get.put(LoginStateController());

// 按钮点击事件
onPressed: () {
  final String email = emailController.text;
  final String pass = pwController.text;
  loginController.login(email, pass);
}

// 在UI中监听状态变化
Obx(() {
  if (loginController.isLoading.value) {
    return CircularProgressIndicator();
  } else if (loginController.errorMsg.value.isNotEmpty) {
    return Text(
      loginController.errorMsg.value,
      style: TextStyle(color: Colors.red),
    );
  } else {
    return MaterialButton(/* 原按钮代码 */);
  }
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 05:10:32