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

Flutter开发中Cubit结果为何在第二个TextField输入前显示

问题原因
  • 当前使用StatelessWidget,build方法内定义的str变量是局部临时变量,点击提交修改str不会触发UI重建,无法控制校验组件的显隐
  • 初始化阶段str和mycontroller.text都为空值,if (str == mycontroller.text)条件直接成立,导致校验结果提前渲染
  • Cubit使用逻辑错误:没有通过emit发送状态,而是直接调用方法返回字符串,没有用到Bloc状态管理的能力,也无法通过状态控制结果显隐
  • TextEditingController在StatelessWidget中使用无法正确释放,会造成内存泄漏
修复方案

1. 修正SentenceCubit逻辑

将校验逻辑改为 emit 对应状态,而不是直接返回字符串:

import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';

part 'sentence_state.dart';

class SentenceCubit extends Cubit<SentenceState> {
  SentenceCubit() : super(SentenceInitial());

  void checkForError(String secondInput, String originalInput) {
    if (secondInput.trim() == originalInput.trim()) {
      emit(Success(okay: "OKAY"));
    } else {
      emit(Failed(notOkay: "Not Okay"));
    }
  }

  // 重置状态的方法,用户输入修改时清空结果
  void resetState() {
    emit(SentenceInitial());
  }
}

2. 将页面改为StatefulWidget,调整UI逻辑

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:rafia_unscramble_demo/cubit/sentence_cubit.dart';

class ScrambledUnscrambled extends StatefulWidget {
  final String? userInputFromFirstTextField;

  const ScrambledUnscrambled({
    super.key,
    required this.userInputFromFirstTextField,
  });

  @override
  State<ScrambledUnscrambled> createState() => _ScrambledUnscrambledState();
}

class _ScrambledUnscrambledState extends State<ScrambledUnscrambled> {
  late final TextEditingController mycontroller;
  // 缓存打乱后的字符串,避免每次build重新打乱
  late final String shuffledSentence;

  @override
  void initState() {
    super.initState();
    mycontroller = TextEditingController();
    // 初始化时就生成唯一的打乱字符串
    final inputs = widget.userInputFromFirstTextField!.split(" ");
    inputs.shuffle();
    shuffledSentence = inputs.join(" ");
  }

  @override
  void dispose() {
    mycontroller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider<SentenceCubit>(
      create: (context) => SentenceCubit(),
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Unscramble'),
        ),
        body: Column(
          children: [
            Card(
              margin: const EdgeInsets.only(top: 50),
              child: Container(
                alignment: Alignment.center,
                width: double.infinity,
                height: 100,
                color: Colors.blueAccent,
                padding: const EdgeInsets.all(15),
                child: Text(
                  shuffledSentence,
                  style: const TextStyle(
                    fontSize: 20,
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                  ),
                ),
              ),
            ),
            const SizedBox(height: 20),
            Container(
              padding: const EdgeInsets.all(20),
              alignment: Alignment.center,
              child: TextField(
                controller: mycontroller,
                onChanged: (String text) {
                  // 用户修改输入时清空之前的校验结果
                  context.read<SentenceCubit>().resetState();
                },
                decoration: InputDecoration(
                  border: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(10),
                  ),
                  hintText: 'Please, enter a grammatically correct sentence.',
                  labelText: 'Second Input',
                  labelStyle: TextStyle(
                    fontSize: 24,
                    color: Colors.blue[900],
                  ),
                ),
              ),
            ),
            ElevatedButton(
              onPressed: () {
                // 点击提交触发校验
                context.read<SentenceCubit>().checkForError(
                  mycontroller.text,
                  widget.userInputFromFirstTextField!,
                );
              },
              child: const Text("Submit"),
            ),
            BlocBuilder<SentenceCubit, SentenceState>(
              builder: (context, state) {
                // 根据状态显示对应内容,初始状态不显示
                if (state is Success) {
                  return Container(
                    color: Colors.green,
                    padding: const EdgeInsets.all(20),
                    width: double.infinity,
                    height: 100,
                    child: Center(
                      child: Text(
                        state.okay,
                        style: const TextStyle(color: Colors.white, fontSize: 24),
                      ),
                    ),
                  );
                } else if (state is Failed) {
                  return Container(
                    color: Colors.redAccent,
                    padding: const EdgeInsets.all(20),
                    width: double.infinity,
                    height: 100,
                    child: Center(
                      child: Text(
                        state.notOkay,
                        style: const TextStyle(color: Colors.white, fontSize: 24),
                      ),
                    ),
                  );
                }
                // 初始状态返回空组件,不显示结果
                return const SizedBox.shrink();
              },
            ),
          ],
        ),
      ),
    );
  }
}
修复后效果
  • 页面初始化时不会显示校验结果
  • 用户输入修改时会自动清空之前的校验提示
  • 只有点击提交按钮后才会触发校验,根据匹配结果显示对应提示
  • 打乱后的字符串不会因为UI重建反复变更,符合功能预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 08:54:05