【问题标题】:How to sync Flutter TextField with Firestore field?如何将 Flutter TextField 与 Firestore 字段同步?
【发布时间】:2018-09-22 11:36:28
【问题描述】:

我在 Firestore 中有 task 文档,其中有 todo 字段,在 Flutter UI 中有 TextField

请告知如何使textfieldtodo 字段同步,即

  1. 任何时候,textfield 中的文本会随着用户的输入而更改,请使用刚刚输入的值更新 todo 字段。
  2. todo 字段随时更新(在 Firestore 控制台中或由其他用户手动更新),将 textfield 更新为最新值。

谢谢!

【问题讨论】:

    标签: firebase flutter google-cloud-firestore


    【解决方案1】:

    首先,将TextEditingController 提供给TextField(查看this 以获得完整示例)。

    对于问题的第一部分,您需要向TextEditingController 提供listener。这个listener 应该触发这样的函数:

      Future<void> _updateTaskValue(String text) {
        Firestore().runTransaction((Transaction transaction) {
          Firestore.instance.document([PATH OF YOUR DOCUMENT]).updateData({"todo": text});
        });
      }
    

    假设text 是控制器的text 值。注意runTransaction是用来避免数据并发的。

    对于问题的第二部分,您必须听文档。为此,请在 initStateStreamSubscription 中声明:

    subscription = Firestore.instance.document("").snapshots().listen(
        (DocumentSnapshot snapshot) => this._onDatabaseUpdate(snapshot));
    

    每次更新内容时,此订阅都会触发一个函数(无论是当前用户更新TextField,其他用户更新它,还是从后台手动更新)。

    下面调用的函数只是用新内容更新控制器的text 属性:

    void _onDatabaseUpdate(DocumentSnapshot snapshot) {
      setState(() {
        _controller.text = snapshot.data["todo"];
      });
    }
    

    有关完整示例,请参阅this gist

    【讨论】:

      【解决方案2】:
      1. TextField onChanged 更新 firebase 中的值。
      2. 监听 firebase 中的值变化并使用 TextEditingController 更新 TextField 的值。

      代码如下:

      import 'dart:async';
      import 'package:firebase_database/firebase_database.dart';
      import 'package:flutter/material.dart';
      
      void main() => runApp(MyApp());
      
      class MyApp extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return MaterialApp(
            title: 'TODO Screen',
            theme: ThemeData(
              primarySwatch: Colors.orange,
            ),
            home: TODOScreen(),
          );
        }
      }
      
      class TODOScreen extends StatefulWidget {
        @override
        _TODOScreenState createState() => _TODOScreenState();
      }
      
      class _TODOScreenState extends State<TODOScreen> {
        final _ref = FirebaseDatabase.instance.reference().child('todo_id').child('value');
        TextEditingController _todoController = new TextEditingController();
      
        StreamSubscription _subscription;
      
        @override
        void initState() {
          super.initState();
          _subscription = _ref.onValue.listen((data) {
            String value = data.snapshot.value as String ?? "";
            updateOnChanged(value);
          });
        }
      
        saveOnChanged(String value) async {
          await _ref.set(value);
        }
      
        updateOnChanged(String value) async {
          setState(() {
            _todoController.value = _todoController.value.copyWith(
              text: value,
            );
          });
        }
      
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            appBar: AppBar(
              title: Text('TODO Screen'),
            ),
            body: Center(
              child: Container(
                padding: EdgeInsets.all(10.0),
                child: TextField(
                  decoration: InputDecoration(labelText: "TODO"),
                  maxLines: 5,
                  onChanged: saveOnChanged,
                  controller: _todoController,
                ),
              ),
            ),
          );
        }
      
        @override
        void dispose() {
          _todoController.dispose();
      
          if (_subscription != null) _subscription.cancel();
      
          super.dispose();
        }
      }
      

      希望有帮助!

      【讨论】:

        猜你喜欢
        • 2021-11-16
        • 2021-04-27
        • 2021-01-03
        • 1970-01-01
        • 2021-06-13
        • 2020-04-16
        • 2017-07-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多