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

Flutter中TextField的onChanged赋值变量无效,回调更新变量后打印仍为null的问题排查

Fixing TextField onChanged Not Updating Variable in Flutter

Hey there! Let's break down why your newTaskTitle variable is showing up as null when you print it, and how to fix this issue.

The Root Cause

You’ve defined String? newTaskTitle; directly inside the widget’s body (which lives within the build method). Here’s the problem: Flutter rebuilds the widget tree frequently—like when the keyboard pops up, or any state changes in your app. Every time this happens, the build method runs again, and your newTaskTitle variable gets reinitialized to null—even if you’d set it via onChanged earlier. That’s why tapping the "Add" button prints null instead of your input text.

Solution 1: Use a StatefulWidget's Member Variable

Move your newTaskTitle variable into the state class of a StatefulWidget (not inside the build method). This way, the variable’s value persists across widget rebuilds.

Here’s the corrected code:

class TaskAddScreen extends StatefulWidget {
  const TaskAddScreen({super.key});

  @override
  State<TaskAddScreen> createState() => _TaskAddScreenState();
}

class _TaskAddScreenState extends State<TaskAddScreen> {
  // Store the variable here, not inside build()
  String? newTaskTitle;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          TextField(
            cursorColor: Colors.white38,
            decoration: const InputDecoration(
              enabledBorder: UnderlineInputBorder(
                borderSide: BorderSide(color: Colors.white38),
              ),
              focusedBorder: UnderlineInputBorder(
                borderSide: BorderSide(color: Colors.white38),
              ),
            ),
            textAlign: TextAlign.center,
            autofocus: true,
            onChanged: (newText) {
              // Update the state variable directly
              newTaskTitle = newText;
            },
          ),
          const SizedBox(height: 20),
          FlatButton(
            color: Colors.white,
            onPressed: () {
              print(newTaskTitle); // Now this will print your input text!
            },
            child: const Text(
              'Add',
              style: TextStyle(
                fontSize: 15,
                fontWeight: FontWeight.bold,
                color: Colors.black,
              ),
            ),
          ),
        ],
      ),
    );
  }
}

For managing TextField input, Flutter’s TextEditingController is the more robust approach. It handles text state internally, so you don’t need to manually update a variable via onChanged.

Here’s how to implement it:

class TaskAddScreen extends StatefulWidget {
  const TaskAddScreen({super.key});

  @override
  State<TaskAddScreen> createState() => _TaskAddScreenState();
}

class _TaskAddScreenState extends State<TaskAddScreen> {
  // Initialize the controller
  final TextEditingController _taskController = TextEditingController();

  @override
  void dispose() {
    // Always dispose the controller to avoid memory leaks
    _taskController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          TextField(
            cursorColor: Colors.white38,
            decoration: const InputDecoration(
              enabledBorder: UnderlineInputBorder(
                borderSide: BorderSide(color: Colors.white38),
              ),
              focusedBorder: UnderlineInputBorder(
                borderSide: BorderSide(color: Colors.white38),
              ),
            ),
            textAlign: TextAlign.center,
            autofocus: true,
            controller: _taskController, // Bind the controller to the TextField
          ),
          const SizedBox(height: 20),
          FlatButton(
            color: Colors.white,
            onPressed: () {
              // Get the text directly from the controller
              print(_taskController.text);
            },
            child: const Text(
              'Add',
              style: TextStyle(
                fontSize: 15,
                fontWeight: FontWeight.bold,
                color: Colors.black,
              ),
            ),
          ),
        ],
      ),
    );
  }
}

This approach is better because it gives you extra control—like setting initial text, clearing the input, or listening to text changes with addListener—and it avoids manual state management errors.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 14:57:33