如何将Flutter TextField与Firestore字段同步?

时间:2018-09-22 11:36:29

标签: firebase flutter google-cloud-firestore

我在Firestore中有onDestroy()个文档,其中有task字段,在Flutter UI中有todo

请建议如何使TextFieldtextfield字段同步,即

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

谢谢!

2 个答案:

答案 0 :(得分:2)

首先,向TextEditingController提供一个TextField(有关完整示例,请查看this)。

对于问题的第一部分,您需要向listener提供一个TextEditingControllerlistener应该触发如下功能:

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

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

对于问题的第二部分,您将不得不听文档。为此,请在initState中声明StreamSubscription

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

答案 1 :(得分:0)

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

希望它会帮助您!