กระพือ: ฉันจะดึงข้อความจาก TextEditingController ใน StatefulWidget ที่กำหนดเองได้อย่างไร

ฉันกำลังพยายามทำให้วิดเจ็ต stateful แบบกำหนดเองทำงานได้อย่างกระพือปีก เรียกว่า LetterTextForm และมีการปรับแต่งเค้าโครงและ TextField

ฉันต้องการให้ดึงข้อความที่ป้อนลงใน TextField ของวิดเจ็ตได้ง่ายโดยใช้วิธี getter บางอย่างในเนื้อหาของวิดเจ็ตที่ส่งคืน TextEditingController.text ปัญหาคือเมื่อฉันทำให้ตัวควบคุม TextEditingController เป็นตัวแปรสุดท้ายดังนี้:

class LetterTextForm extends StatefulWidget {

  LetterTextForm({@required this.label, this.prefixIcon});
  final Widget prefixIcon;
  final String label;
  final TextEditingController controller = TextEditingController();
  String get textEntered => controller.text;


  @override
  _LetterTextFormState createState() => _LetterTextFormState();
}

class _LetterTextFormState extends State<LetterTextForm> {
  

  @override
  void initState() {
    super.initState();
  }

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


  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: widget.controller,
        decoration: InputDecoration(
          prefixIcon: widget.prefixIcon,
          labelText: widget.label,
        )
    );
  }
}


เกิดข้อผิดพลาดต่อไปนี้: TextEditingController ถูกใช้หลังจากถูกกำจัด

ฉันคิดว่าบางทีปัญหาก็คือคอนโทรลเลอร์ไม่ควรเป็นที่สิ้นสุด ดังนั้นฉันจึงย้ายคอนโทรลเลอร์ไปที่คลาสสถานะและสร้างฟังก์ชันในคลาสสถานะ textCallback ที่ปรับเปลี่ยน String ที่ไม่ใช่สตริงสุดท้ายที่อยู่ในคลาสวิดเจ็ต วิธีนี้ใช้งานได้ แต่ละเมิดความไม่เปลี่ยนรูปของวิดเจ็ต:


class LetterTextForm extends StatefulWidget {

  LetterTextForm({@required this.label, this.prefixIcon});
  final Widget prefixIcon;
  final String label;
  String text = '';

  String get textEntered => text;



  @override
  _LetterTextFormState createState() => _LetterTextFormState();
}

class _LetterTextFormState extends State<LetterTextForm> {
  var controller = TextEditingController();
  
  void textCallback() {
    widget.text = controller.text;
  }

  @override
  void initState() {
    super.initState();
  }

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


  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: controller,
        decoration: InputDecoration(
          prefixIcon: widget.prefixIcon,
          labelText: widget.label,
        )
    );
  }
}


มีวิธีการทำเช่นนี้หรือไม่ว่าทั้ง 1) ไม่ละเมิดความไม่เปลี่ยนรูปและ 2) ไม่กำจัด TextEditingController() ทันทีเมื่อผู้ใช้กด Enter

มันใช้งานได้เมื่อฉันกำจัดเมธอด dispose() แต่ดูเหมือนว่าอาจทำให้เกิดปัญหาด้านประสิทธิภาพ/ประสิทธิภาพของหน่วยความจำในภายหลัง บางทีฉันไม่รู้ว่าฉันกำลังพูดถึงอะไรที่นั่น...

บางทีฉันควรลองสิ่งที่แตกต่างออกไปโดยสิ้นเชิงและวาง TextEditingControllers ขึ้นไปบนแผนผังพร้อมกับบรรพบุรุษของวิดเจ็ต LetterTextForm และไม่อยู่ภายในวิดเจ็ตภายใน


person Jackson    schedule 24.12.2020    source แหล่งที่มา


คำตอบ (1)


สร้างสมาชิกโทรกลับ ValueChanged<String> และโทรกลับเมื่อข้อมูลเสร็จสมบูรณ์

class LetterTextForm{
  ...
  final ValueChanged<String> onChanged;
  ...
}

class _LetterTextFormState extends ... {
  final _controller = TextEditingController();
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(...) {
    return TextField(
      controller: _controller,
      onSubmitted: (value) {
        if (widget.onChanged != null) {
          widget.onChanged(value); // returns entered value to caller
        }
      },
    );
  }
}

ป.ล. หากใช้ TextFormField ก็ไม่จำเป็นต้องใช้คอนโทรลเลอร์ และคุณสามารถใช้ initialData เพื่อเริ่มต้นได้

person BambinoUA    schedule 25.12.2020