Flutter: Bagaimana cara mengambil teks dari TextEditingController di StatefulWidget khusus?

Saya mencoba membuat widget stateful khusus berfungsi di flutter. Ini disebut LetterTextForm, dan berisi beberapa penyesuaian tata letak dan TextField.

Saya ingin mudah mengambil teks yang dimasukkan ke dalam TextField widget, dengan semacam metode pengambil di badan widget yang mengembalikan TextEditingController.text. Masalahnya adalah, ketika saya menjadikan pengontrol TextEditingController sebagai variabel akhir seperti ini:

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,
        )
    );
  }
}


kesalahan berikut terjadi: TextEditingController digunakan setelah dibuang.

Saya pikir mungkin masalahnya adalah pengontrolnya belum final, jadi saya memindahkan pengontrol ke kelas negara bagian dan membuat fungsi di kelas negara, textCallback, yang mengubah String non-final yang ada di kelas widget. Cara ini berfungsi tetapi melanggar kekekalan widget:


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,
        )
    );
  }
}


Apakah ada cara untuk melakukan ini agar 1) tidak melanggar kekekalan dan 2) tidak langsung membuang TextEditingController() saat pengguna menekan Enter?

Ini berfungsi ketika saya menyingkirkan metode buang(), tetapi sepertinya itu dapat menyebabkan beberapa masalah kinerja/efisiensi memori di kemudian hari. Mungkin saya tidak tahu apa yang saya bicarakan di sana...

Mungkin saya harus mencoba sesuatu yang sama sekali berbeda dan menempatkan TextEditingControllers lebih jauh di pohon dengan nenek moyang widget LetterTextForm, dan bukan secara internal di dalam widget?


person Jackson    schedule 24.12.2020    source sumber


Jawaban (1)


Buat anggota panggilan balik ValueChanged<String> dan panggil kembali ketika data sudah selesai.

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
        }
      },
    );
  }
}

P.S. Jika menggunakan TextFormField maka pengontrol tidak diperlukan dan Anda dapat menggunakan initialData untuk inisialisasi.

person BambinoUA    schedule 25.12.2020