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

使用GetX时Flutter UI仅热重载后才刷新的问题求助

问题分析与解决方案

你遇到的UI不自动刷新问题,核心原因有两个:控制器实例可能不唯一,以及主题颜色的获取方式错误导致Flutter无法正确识别状态变化。以下是具体的修复步骤和代码调整:


修复步骤

1. 确保控制器全局唯一

在页面中直接使用Get.put()可能会重复创建控制器实例(尤其是页面被多次打开时),导致页面监听的实例与状态变更的实例不一致。正确的做法是在应用入口初始化控制器,页面中用Get.find()获取已存在的实例。

2. 修正主题颜色获取方式

直接调用ThemeData.dark()会每次生成新的ThemeData实例,即使颜色值相同,Flutter也可能判定为“未变化”,从而不触发UI更新。应使用当前上下文的主题颜色。

3. 统一状态更新方法

使用update()(GetXController的标准更新方法)替代refresh(),确保状态变更能正确通知到UI。


修改后的代码

1. 应用入口初始化控制器(main.dart)

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'path_to_your_controller/expenses_controller.dart';
import 'path_to_your_screen/new_expense_screen.dart';

void main() {
  // 全局初始化控制器,确保唯一实例
  Get.put(ExpensesController());
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Budget App',
      theme: ThemeData.dark(),
      home: const NewExpenseScreen(),
    );
  }
}

2. 修改ExpensesController的状态更新方法

import 'package:annual_budget/backend/model/spending_categories.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

class ExpensesController extends GetxController {
  var expenseCategories = [].obs;
  var expenseSubcategories = [].obs;
  var selectedCategoryName = ''.obs;
  var selectedSubcategoryName = ''.obs;

  @override
  void onInit() {
    super.onInit();
    expenseCategories.value = [
      Category(
        icon: Icons.all_inclusive_rounded,
        name: 'Everyday',
        subcategories: {
          SubCategory(icon: Icons.local_grocery_store, name: 'Groceries'),
          SubCategory(icon: Icons.restaurant, name: 'Restaurant'),
          SubCategory(icon: Icons.delivery_dining, name: 'Food Order'),
        },
      ),
      Category(
        icon: Icons.travel_explore,
        name: 'Travel',
        subcategories: {
          SubCategory(icon: Icons.airplane_ticket_outlined, name: 'Transportation'),
          SubCategory(icon: Icons.food_bank_rounded, name: 'Food'),
          SubCategory(icon: Icons.house, name: 'Accomodation'),
        },
      ),
      Category(
        icon: Icons.pets_rounded,
        name: 'Pet',
        subcategories: {
          SubCategory(icon: Icons.food_bank, name: 'Food'),
          SubCategory(icon: Icons.medical_services, name: 'Veterinary'),
        },
      ),
    ];
  }

  void setSubcategories(Set<SubCategory> subcategories, String categoryName) {
    selectedCategoryName.value = categoryName;
    expenseSubcategories.value = subcategories.toList();
    update(); // 通知UI更新,GetBuilder和Obx都能识别
  }
}

3. 修改NewExpenseScreen的控制器获取与颜色逻辑

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'path_to_your_controller/expenses_controller.dart';
import 'path_to_your_model/spending_categories.dart';

class NewExpenseScreen extends StatelessWidget {
  static const String route = 'new_expense_screen2';
  // 获取全局唯一的控制器实例
  final ExpensesController exc = Get.find<ExpensesController>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: AppBar(
        leading: MaterialButton(
          onPressed: () => Navigator.of(context).pop(),
          child: const Icon(Icons.arrow_back_ios_new_rounded),
        ),
        title: const Text('Add a new Expense'),
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 10.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Expanded(
              child: Obx(
                () => ListView.builder(
                    itemCount: exc.expenseCategories.length,
                    itemBuilder: (context, index) {
                      Category category = exc.expenseCategories[index];
                      final isSelected = category.name == exc.selectedCategoryName.value;

                      return MaterialButton(
                        color: isSelected
                            ? Theme.of(context).colorScheme.secondary
                            : Theme.of(context).colorScheme.background,
                        onPressed: () {
                          exc.setSubcategories(category.subcategories, category.name);
                          FocusManager.instance.primaryFocus?.unfocus();
                        },
                        child: Padding(
                          padding: const EdgeInsets.symmetric(vertical: 10),
                          child: Column(
                            children: [
                              Icon(
                                category.icon,
                                color: isSelected ? Colors.black : Colors.white,
                              ),
                              Text(
                                category.name,
                                style: TextStyle(
                                  color: isSelected ? Colors.black : Colors.white,
                                ),
                              )
                            ],
                          ),
                        ),
                      );
                    }),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 07:43:10