# #firebase #flutter #dart #firebase-realtime-database
Вопрос:
Поэтому в настоящее время у меня есть база данных в Firebase, содержащая информацию, которую я показываю пользователям. И как администратор, я хочу обновить информацию. Однако, когда я пытаюсь обновить его, вместо этого в базу данных Firebase в реальном времени добавляется новая запись.
Это код, который отображает все записи в базе данных в реальном времени, и значок редактирования, который перенаправляет его на страницу обновления:
class _UpdateDestinationsState extends Statelt;UpdateDestinationsgt; { final destdatabaseref = FirebaseDatabase.instance .reference() .child('Database') .child('DestinationsandActivities') .orderByChild("category") .equalTo("Destination"); @override @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( iconTheme: IconThemeData(color: Colors.white), //add this line here backgroundColor: Color(0xFF3d5a89), elevation: 0, centerTitle: true, title: const Text('Update Destinations', style: TextStyle( fontSize: 18, fontWeight: FontWeight.w500, color: Colors.white)), ), body: SafeArea( child: FirebaseAnimatedList( query: destdatabaseref, itemBuilder: (BuildContext context, DataSnapshot snapshot, Animationlt;doublegt; animation, int index) { return ListTile( title: Text(snapshot.value['name']), trailing: IconButton( onPressed: () { Navigator.of(context).push(MaterialPageRoute( builder: (context) =gt; UpdatePage( name: snapshot.value['name'], description: snapshot.value['description'], id: snapshot.value['id'], ))); }, icon: Icon(Icons.edit)), ); })), ); } }
А это код страницы обновления, на которой вы можете редактировать информацию:
class UpdatePage extends StatefulWidget { final String name; final String description; final String id; UpdatePage( {Key? key, required this.name, required this.description, required this.id}) : super(key: key); @override _UpdatePageState createState() =gt; _UpdatePageState(); } class _UpdatePageState extends Statelt;UpdatePagegt; { final destdatabaseref = FirebaseDatabase.instance .reference() .child('Database') .child('DestinationsandActivities'); @override Widget build(BuildContext context) { final nameController = TextEditingController(); final descriptionController = TextEditingController(); setState(() { nameController.text = widget.name; descriptionController.text = widget.description; }); return Scaffold( appBar: AppBar( iconTheme: IconThemeData(color: Colors.white), backgroundColor: Color(0xFF3d5a89), elevation: 0, centerTitle: true, title: const Text('Update Destinations', style: TextStyle( fontSize: 18, fontWeight: FontWeight.w500, color: Colors.white)), ), body: Form( child: Padding( padding: EdgeInsets.all(8), child: Column( children: [ TextFormField( controller: nameController, autofocus: false, decoration: InputDecoration( labelText: 'Name', border: OutlineInputBorder(), ), ), SizedBox(height: 10), TextFormField( controller: descriptionController, autofocus: false, decoration: InputDecoration( labelText: 'Description', border: OutlineInputBorder(), ), ), TextButton( onPressed: () { updateData(widget.name, widget.description, widget.id); Navigator.pop(context); }, child: Text('Update')), TextButton( onPressed: () { Navigator.of(context).pop(); }, child: Text('Cancel')), ], ), ), )); } void updateData(String name, String description, var key) { Maplt;String, Stringgt; newvalue = {'name': name, 'description': description}; destdatabaseref.child(key).update(newvalue); } }
С помощью этого кода я получаю запись такого типа, добавленную в мою базу данных в реальном времени, когда я нажимаю обновить текст.:
Как я могу это исправить?
Ответ №1:
Я думаю, что проблема заключается в получении идентификатора.
В реальном времени будет использовать сгенерированный ключ (ID), если вы передаете значение null, я никогда не использовал FirebaseAnimatedList
раньше, но я видел пример, где они обращались с snapshot.key
….
Но я уверен, что это не snapshot.value['id']
потому, что в вашей структуре нет ID с именем и украшения, и он будет возвращен как объект, идентификатор не будет поля для доступа к нему.
Так что попробуйте сначала печатать snapshot.value['id']
, если он содержит идентификатор пропустите мой ответ, если его значение null, попробовать snapshot.key
, посмотреть, как моментальный снимок структурированный с FirebaseAnimatedList если это тоже не сработало.
Комментарии:
1. Эй, спасибо! Я думаю, это может сработать. Тем не менее, я объявляю
snapshot.key
как var вUpdatePage
классе вместо окончательной строки, и я получаю »This class (or a class that this class inherits from) is marked as '@immutable', but one or more of its instance fields aren't final: UpdatePage.id
»2. Вам не нужно этого делать, оставьте
UpdatePage
класс таким, как он есть, просто измените то, что вы за него выдаете:onPressed: () { Navigator.of(context).push(MaterialPageRoute( builder: (context) =gt; UpdatePage( name: snapshot.value['name'], description: snapshot.value['description'], id: snapshot.key, //lt;-- here ))); },
3. Я так и сделал, но в нем это сказано
The argument type 'String?' can't be assigned to the parameter type 'String'
.4. Я не знаю, знаете ли вы, что это значит, но это связано с нулевой безопасностью, где»? » означает, что эта строка может быть нулевой, если вы ее не добавите, то это значение не может быть нулевым, что и происходит здесь, где страница обновления не может принимать нулевое значение для любого из своих параметров. Чтобы решить эту проблему, есть несколько простых способов: — (нехорошо) разрешить странице обновления принимать нулевое значение с помощью ‘?’:
final String? id;
что нехорошо, потому что вам нужен идентификатор. — проверьте значение перед вызовом:onPressed:() { if(snapshot.key!=null){Navigator.of(context)...}
Для дополнительной проверки(и устранения ошибки) передайте:snapshot.key??''
5. Я пробовал! Определенно устраняет
The argument type 'String?' can't be assigned to the parameter type 'String'
ошибку, но данные все еще не могут быть обновлены.
Ответ №2:
Наконец-то я обнаружил ошибку. updateData(widget.name, widget.description, widget.id);
Должно быть: updateData(nameController.text, descriptionController.text, widget.id);
вместо этого.