Как мне обновить виджет BuildList, чтобы он оставался с состоянием во флаттере с отслеживаемым контекстом из FireStore - PullRequest
0 голосов
/ 19 января 2019

Я уже давно борюсь с этим кодом, поэтому я решил спросить сообщество.

Я начинаю свой путь программирования с Flutter и использую код, найденный на сайте:

https://medium.com/@durannumit/my-flutter-adventure-flutter-on-fire-93f7e676ff83

Я изменил его.

Приложение добавляет имена детей, используя TextField.Это правильно добавляет имена в ListView, который остается с состоянием и изменяется при изменении состояния переменной в базе данных.Затем вы можете нажать на ячейку, чтобы перейти на другую страницу.Код, найденный в MyHomePage.dart, работает правильно.

Проблема в том, когда я перехожу на следующую страницу.Я хочу добавить каждую детскую информацию: (имя, родители, birthMonth и голоса) в ListView.

Предполагается, что значение голоса изменится при нажатии любой из ячеек таблицы.Вот где проблема.Значение не изменяется на странице.

Я считаю, что я сузил его до значения записи виджета _buildList SpecificRecordDetailsPage, который не обновляется.Я пометил функцию Widget с помощью ****

Может кто-нибудь сказать мне, что я делаю не так?

Код:

main.dart

import 'package:baby_names/MyHomePage.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Baby Names',
      home: MyHomePage(),
    );
  }
}

MyHomePage.dart

import 'package:baby_names/Record.dart';
import 'package:baby_names/SpecificRecordDetailsPage.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() {
    return _MyHomePageState();
  }
}

class _MyHomePageState extends State<MyHomePage> {
  final TextEditingController eCtrl = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Baby Name Votes')),
      body: Column(
        children: <Widget>[
          Padding(
            padding: EdgeInsets.fromLTRB(20, 0, 20, 0),
            child: TextField(
              decoration: InputDecoration(hintText: "Add a Baby's Name"),
              controller: eCtrl,
              onSubmitted: (text) {
                if (text != null) {
                  if (text.isNotEmpty) {
                    Firestore.instance.collection('baby').document().setData({
                      'name': text,
                      'votes': 0,
                      'parents': "Mum and Dad",
                      'birthMonth': "June"
                    });
                    eCtrl.clear();
                  }
                }
              },
            ),
          ),
          Expanded(child: _buildBody(context)),
        ],
      ), //_buildBody(context),
    );
  }

  Widget _buildBody(BuildContext context) {
    return StreamBuilder<QuerySnapshot>(
      stream: Firestore.instance.collection('baby').snapshots(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) return LinearProgressIndicator();
        return _buildList(context, snapshot.data.documents);
      },
    );
  }

  Widget _buildList(BuildContext context, List<DocumentSnapshot> snapshot) {
    return ListView(
      padding: const EdgeInsets.only(top: 20.0),
      children: snapshot.map((data) => _buildListItem(context, data)).toList(),
    );
  }

  Widget _buildListItem(BuildContext context, DocumentSnapshot data) {
    final record = Record.fromSnapshot(data);

    return Padding(
      key: ValueKey(record.reference),
      padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
      child: Container(
        decoration: BoxDecoration(
          border: Border.all(color: Colors.grey),
          borderRadius: BorderRadius.circular(5.0),
        ),
        child: ListTile(
          title: Text(record.name),
          onTap: () {
            Navigator.of(context).push(MaterialPageRoute(
                builder: (_) => SpecificRecordDetailsPage(record: record)));
          },
        ),
      ),
    );
  }
}

SpecificRecordDetailsPage.dart

import 'package:baby_names/Record.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

class SpecificRecordDetailsPage extends StatefulWidget {
  final Record record;

  SpecificRecordDetailsPage({this.record});

  @override
  SpecificRecordDetailsPageState createState() {
    return new SpecificRecordDetailsPageState(record: record);
  }
}

class SpecificRecordDetailsPageState extends State<SpecificRecordDetailsPage> {
  final Record record;

  SpecificRecordDetailsPageState({this.record});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Baby Details')),
      body: _buildBody(context),
    );
  }

  Widget _buildBody(BuildContext context) {
    //The listener comes from the StreamBuilder, it is what cause the SetState().
    return StreamBuilder<QuerySnapshot>(
      stream: Firestore.instance
          .collection('baby')
          .where('name', isEqualTo: record.name)
          .snapshots(),
      builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
        if (!snapshot.hasData) return LinearProgressIndicator();

        return _buildList(context, snapshot.data.documents);
      },
    );
  }


// ***I BELIEVE THAT THIS IS WHERE THE PROBLEM IS LOCATED***. 

  Widget _buildList(BuildContext context, List<DocumentSnapshot> snapshot) {
    var details = [record.name, record.parents, record.birthMonth];

    return ListView.builder(
      key: ValueKey(record.votes),
      itemBuilder: (context, int index) {
        return ListTile(
          leading: Text(details[index]),
          title: Text("${record.votes}"),
          onTap: () =>
              Firestore.instance.runTransaction((transaction) async {
                final freshSnapshot = await transaction.get(record.reference);
                final fresh = Record.fromSnapshot(freshSnapshot);

                await transaction
                    .update(record.reference, {'votes': fresh.votes + 1});
              }),
        );
      },
      itemCount: details.length,
    );
  }

Запись.dart

import 'package:cloud_firestore/cloud_firestore.dart';

class Record {
  final String name;
  final int votes;
  final String birthMonth;
  final String parents;
  final DocumentReference reference;

  Record.fromMap(Map<String, dynamic> map, {this.reference})
      : assert(map['name'] != null),
        assert(map['votes'] != null),
        assert(map['parents'] != null),
        assert(map['birthMonth'] != null),
        name = map['name'],
        votes = map['votes'],
        parents = map['parents'],
        birthMonth = map['birthMonth'];

  Record.fromSnapshot(DocumentSnapshot snapshot)
      : this.fromMap(snapshot.data, reference: snapshot.reference);

  @override
  String toString() => "Record<$name:$votes>";
}

Любая помощь будет наиболее ценной для моего обучения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...