flutter使用getx做一个todolist

如图最终效果:

实现步骤:

一、创建基础文件

创建test_controller.dart、test_binding.dart、test_view.dart、index.dart文件,分别对应逻辑层、依赖注入层、视图层、模块入口

复制代码
路由跳转 → TestBinding 初始化 TestController → TestView 获取控制器并渲染 UI  
→ 用户操作触发 Controller 方法 → Controller 更新状态 → Obx 驱动 UI 刷新  
→ 页面关闭 → GetX 销毁 Controller 并调用 onClose()  
(全程通过 index.dart 简化外部引用)
Dart 复制代码
//test_binding.dart文件代码
import 'package:app3/views/test/test_controller.dart';
import 'package:get/get.dart';

class TestBinding extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut(() => TestController());
  }
}
Dart 复制代码
//index.dart代码
export 'test_binding.dart';
export 'test_controller.dart';
export 'test_view.dart';

二、test_controller.dart中写状态、增删改查方法

Dart 复制代码
//test_controller.dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';

class TestController extends GetxController {
  @override
  void onInit() {
    super.onInit();
    print('初始化生命周期函数:$todoList');
    
    // 使用 ever 监听 todoList 的变化
    ever(todoList, (newValue) {
      print("todoList 变化了,新值:$newValue");
    });
  }

  @override
  void onReady() {
    super.onReady();
    print('UI 首次构建完成:$todoList');
  }

  @override
  void onClose() {
    super.onClose();
    print('页面关闭:$todoList');
  }

  final RxList<Map<String, dynamic>> todoList = <Map<String, dynamic>>[
    {'title': '吃饭', 'isDone': true},
    {'title': '睡觉', 'isDone': false},
    {'title': '打游戏', 'isDone': false},
    {'title': '学习', 'isDone': false},
    {'title': '看电影', 'isDone': false},
    {'title': '看小说', 'isDone': false},
  ].obs;

  void add(Map<String, dynamic> item) {
    todoList.add(item);
  }

  void delete(int index) {
    todoList.removeAt(index);
  }

  void showDeleteDialog(int index) {
    Get.dialog(
      AlertDialog(
        title: const Text('确定要删除吗?'),
        content: const Text('删除后将无法恢复'),
        actions: [
          TextButton(
              onPressed: () {
                Get.back();
              },
              child: const Text('取消')),
          TextButton(
              onPressed: () {
                delete(index);
                Get.back();
              },
              child: const Text('确定')),
        ],
      ),
    );
  }
  void showAddDialog() {
    final TextEditingController textController = TextEditingController();

    Get.dialog(
      AlertDialog(
        title: const Text('添加待办事项'),
        content: TextField(
          controller: textController,
          decoration: const InputDecoration(
            hintText: '请输入标题',
            border: OutlineInputBorder(),
          ),
          autofocus: true,
        ),
        actions: [
          TextButton(
              onPressed: () {
                Get.back();
              },
              child: const Text('取消')),
          TextButton(
              onPressed: () {
                if (textController.text.trim().isNotEmpty) {
                  add({'title': textController.text.trim(), 'isDone': false});
                  Get.back();
                }
              },
              child: const Text('确定')),
        ],
      ),
    );
  }

  void finish(int index) {
    todoList[index]['isDone'] = !todoList[index]['isDone'];
    todoList.refresh(); // 手动触发更新
  }
}

三、test_view.dart文件视图渲染

Dart 复制代码
import 'package:app3/views/test/test_controller.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

class TestView extends GetView<TestController> {
  const TestView({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: const Text('todolist')),
        body: Column(
          children: [
            Expanded(
              child: Obx(() => ListView.builder(
                itemCount: controller.todoList.length,
                // 构建每个列表项
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                    leading: Checkbox(
                      value: controller.todoList[index]['isDone'], 
                      onChanged: (value) {
                        controller.finish(index);
                      }
                    ),
                    title: Text(
                      '${controller.todoList[index]['title']}',
                      style: TextStyle(
                        decoration: controller.todoList[index]['isDone'] 
                          ? TextDecoration.lineThrough 
                          : TextDecoration.none,
                        color: controller.todoList[index]['isDone']
                          ? Colors.grey
                          : null,
                      ),
                    ),
                    subtitle: Text('这是第${index + 1}个条目'),
                    trailing: IconButton(
                      onPressed: () {
                        controller.showDeleteDialog(index);
                      }, 
                      icon: const Icon(Icons.delete)
                    ),
                  );
                },
              )),
            )
          ],
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            controller.showAddDialog();
          },
          child: const Icon(Icons.add),
        ),
    );
  }
}
相关推荐
徐子童1 天前
网络协议---TCP协议
网络·网络协议·tcp/ip·面试题·1024程序员节
扫地的小何尚3 天前
NVIDIA RTX PC开源AI工具升级:加速LLM和扩散模型的性能革命
人工智能·python·算法·开源·nvidia·1024程序员节
数据皮皮侠AI4 天前
上市公司股票名称相似度(1990-2025)
大数据·人工智能·笔记·区块链·能源·1024程序员节
开开心心就好4 天前
系统清理工具清理缓存日志,启动卸载管理
linux·运维·服务器·神经网络·cnn·pdf·1024程序员节
Evan东少7 天前
[踩坑]笔记本Ubuntu20.04+NvidiaRTX5060驱动+cuda+Pytorch+ROS/Python实现人脸追踪(环境准备)
1024程序员节
不爱编程的小陈8 天前
C/C++每日面试题
面试·职场和发展·1024程序员节
开开心心就好8 天前
右键菜单管理工具,添加程序自定义名称位置
linux·运维·服务器·ci/cd·docker·pdf·1024程序员节
码农三叔9 天前
(4-2-05)Python SDK仓库:MCP服务器端(5)Streamable HTTP传输+Streamable HTTP传输
开发语言·python·http·大模型·1024程序员节·mcp·mcp sdk
西幻凌云13 天前
初始——正则表达式
c++·正则表达式·1024程序员节
启芯硬件13 天前
电源XL6009E1的dieshot细节分析-芯片设计干货
大数据·经验分享·硬件工程·1024程序员节