Не удается обновить данные в базе данных в реальном времени

# #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); вместо этого.