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

Flutter中用Obx结合REST API渲染ListView的加载问题排查

问题:GetX页面首次加载无数据,热重载后正常显示

控制器代码

import 'dart:convert';
import 'package:get/get.dart';
import '../../../functions/functions.dart';
import '../models/user_details_modal.dart';

class UserListController extends GetxController {
  var data = [];
  List<UserDetails> userDetails = <UserDetails>[].obs;
  // var userDetails = <UserDetails>[].obs;
  // RxList<UserDetails> userDetails = <UserDetails>[].obs;
  // RxList<UserDetails> userDetails = RxList();

  Future<void> fetchData() async {
    String apipage = "getData.php";
    Map mappeddata = {};
    final response = await sendServerData(apipage, mappeddata);

    if (response.statusCode == 200) {
      final responseBody = jsonDecode(response.body.toString());
      userDetails = userDetailsFromJson(json.encode(responseBody));
      print(userDetails);
      update();
    } else {
      Get.snackbar(
          'Server Connection Failed', 'Please try again after some time');
    }
  }

  @override
  void onInit() {
    fetchData();
    super.onInit();
  }
}

视图代码

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/user_list_controller.dart';
import '../models/user_details_modal.dart';

class UserListView extends GetView<UserListController> {
  @override
  final UserListController controller = Get.put(UserListController());
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ListView'),
        centerTitle: true,
      ),
      body: Obx(
        () => controller.userDetails.isEmpty
            ? Center(
                child: Text("Loading data..."),
              )
            : ListView.builder(
                itemCount: controller.userDetails.length,
                itemBuilder: (context, index) {
                  final UserDetails item = controller.userDetails[index];
                  return buildListTile(item);
                },
              ),
      ),
    );
  }

  Widget buildListTile(UserDetails item) {
    print("userName: ${item.userName}"); 
    print("userEmail: ${item.userEmail}");
    return ListTile(
      title: Text(item.userName),
      subtitle: Text(item.userEmail),
      trailing: IconButton(
        icon: const Icon(Icons.edit),
        onPressed: () {},
      ),
    );
  }
}

最初报错

"[Get] the improper use of a GetX has been detected.
You should only use GetX or Obx for the specific widget that will be updated.
If you are seeing this error, you probably did not insert any observable variables into GetX/Obx
or insert them outside the scope that GetX considers suitable for an update
(example: GetX => HeavyWidget => variableObservable).
If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX."

当前问题

修改列表声明解决上述报错后,通过Get.to()跳转至该页面时,首次加载无数据,热重载后数据才正常显示。


问题原因与解决方法

1. 可观察列表的声明与赋值错误

当前代码中,userDetails被声明为普通List<UserDetails>,却赋值了obs创建的RxList,这会丢失可观察性。后续直接赋值新列表时,Obx监听的旧实例未发生变化,因此无法触发页面更新。

修改控制器:

  • 正确声明为RxList类型:
    RxList<UserDetails> userDetails = <UserDetails>[].obs;
    
  • 更新列表时,不要直接替换整个列表实例,而是使用assignAll或addAll修改现有列表:
    if (response.statusCode == 200) {
      final responseBody = jsonDecode(response.body.toString());
      // 用assignAll替换直接赋值,保持同一RxList实例
      userDetails.assignAll(userDetailsFromJson(json.encode(responseBody)));
      print(userDetails);
      // 此处无需调用update(),Obx会自动监听RxList变化
    }
    

2. GetView的错误使用

GetView<UserListController>已经自动通过Get.find()获取控制器实例,无需手动调用Get.put()重复创建,这会导致控制器实例不一致,数据监听失效。

修改视图:

  • 删除手动声明的controller变量,直接使用GetView提供的controller属性:
    class UserListView extends GetView<UserListController> {
      // 删掉这行:@override final UserListController controller = Get.put(UserListController());
      @override
      Widget build(BuildContext context) {
        return Scaffold(...); // 直接使用controller即可
      }
    }
    

完成以上修改后,页面首次加载时,数据请求完成后会触发Obx自动重建,列表数据就能正常显示了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 09:45:28