首页 > 解决方案 > 在 Streambuilder 中使用 TextField

问题描述

我们如何在 StreamBuilder 中添加 TextField?我有一个 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);
}

我想要实现的是从firestore文档中获得一个带有预填充数据的表单,基本上是一个编辑表单。有没有其他方法可以达到同样的效果,或者我在结构上做错了什么?

编辑:

建议编辑后的代码。

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

标签: firebasedartgoogle-cloud-firestoreflutter

解决方案


为了正确使用 StreamBuilder,您必须确保您正在使用的流缓存在 State 对象上。虽然 StreamBuilder 可以正确处理从流中获取新事件,但接收全新的 Stream 将强制它完全重建。在您的情况下,getClientProfile().snapshots()将在调用时创建一个全新的 Stream ,从而破坏文本字段的所有状态。

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) {
        ...

      },
    );
  }
}

编辑:听起来我无法从您提供的代码片段中诊断出其他问题。


推荐阅读