Использование TextField внутри Streambuilder

Как добавить TextField в StreamBuilder? У меня есть TextField / TextFormField в качестве одного из виджетов внутри функции построителя StreamBuilder или FutureBuilder, всякий раз, когда мы пытаемся взаимодействовать с текстовым полем, он просто обновляет весь виджет построителя и снова вызывает поток / будущее.

body: StreamBuilder(
      stream: getClientProfile().snapshots(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.active) {
          print(snapshot.data.data);
          Client tempClient = Client.from(snapshot.data);
          print('details = ${tempClient.representative.email} ${tempClient
              .address.location} ${tempClient.businessDescription}');
          return Container(
            child: Column(
              children: <Widget>[
                TextFormField(

                )
              ],
            ),
          );
        } else if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(child: CircularProgressIndicator());
        } else {
          return Center(
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Icon(Icons.error),
                ),
                Text('Error loading data')
              ],
            ),
          );
        }
      }),

и функция пожарного депо

DocumentReference getClientProfile() {
   return _firestore.collection(SELLERS_COLLECTION).document(_uid);
}

Чего я хочу добиться, так это иметь форму с предварительно заполненными данными из документа пожарного депо, в основном форму для редактирования. Есть ли другой способ, которым я мог бы достичь того же или я делаю что-то не так структурно?

РЕДАКТИРОВАТЬ:

код после предлагаемых изменений.

    import 'package:flutter/material.dart';
import 'Utils/globalStore.dart';
import 'models/client_model.dart';
import 'dart:async';

class EditProfileInformation extends StatefulWidget {
  @override
  EditProfileInformationState createState() {
    return new EditProfileInformationState();
  }
}

class EditProfileInformationState extends State<EditProfileInformation> {
  Stream dbCall;
  final myController = TextEditingController();

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    dbCall = getClientProfile().snapshots();
    myController.addListener(_printLatestValue);
  }

  _printLatestValue() {
    print("Second text field: ${myController.text}");
  }

  @override
  void dispose() {
    myController.removeListener(_printLatestValue);
    myController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
//      key: _scaffoldKey,
      appBar: AppBar(
        title: Text(
          'Edit profile',
          style: TextStyle(),
        ),
      ),

      body: StreamBuilder(
          stream: dbCall,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.active) {
              print(snapshot.data.data);
              Client tempClient = Client.from(snapshot.data);
              print('details = ${tempClient.representative.email} ${tempClient
                  .address.location} ${tempClient.businessDescription}');
              return Container(
                child: Column(
                  children: <Widget>[
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: TextField(
                        controller: myController,
                      ),
                    )
                  ],
                ),
              );
            } else if (snapshot.connectionState == ConnectionState.waiting) {
              return Center(child: CircularProgressIndicator());
            } else {
              return Center(
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Icon(Icons.error),
                    ),
                    Text('Error loading data')
                  ],
                ),
              );
            }
          }),
      floatingActionButton: FloatingActionButton(
        onPressed: () {

        },
        child: Icon(Icons.done),
      ),
    );
  }
}

1 ответ

Для правильного использования StreamBuilder необходимо убедиться, что используемый вами поток кэшируется на объекте State. Несмотря на то, что StreamBuilder может правильно обрабатывать получение новых событий из потока, получение совершенно нового Stream заставит его полностью перестроиться. В твоем случае, getClientProfile().snapshots() при вызове создаст совершенно новый поток, разрушив все состояние ваших текстовых полей.

class Example extends StatefulWidget {
  @override
  State createState() => new ExampleState();
}

class ExampleState extends State<Example> {
  Stream<SomeType> _stream;

  @override
  void initState() {
    // Only create the stream once
    _stream = _firestore.collection(collection).document(id);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return new StreamBuilder(
      stream: _stream,
      builder: (context, snapshot) {
        ...

      },
    );
  }
}

РЕДАКТИРОВАТЬ: похоже, есть другие проблемы, которые я не могу диагностировать из предоставленного вами фрагмента кода.

Другие вопросы по тегам