Я уже давно борюсь с этим кодом, поэтому я решил спросить сообщество.
Я начинаю свой путь программирования с 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>";
}
Любая помощь будет наиболее ценной для моего обучения.