Я получаю NoSuchMethodError при попытке выполнить обновление транзакции в моей коллекции Firestore.
Receiver: null
Tried calling: cast<String, dynamic>()
#0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
#1 MethodChannel.invokeMapMethod (package:flutter/src/services/platform_channel.dart:331:19)
<asynchronous suspension>
#2 Firestore.runTransaction (file:///Users/wready/dev_tools/flutter/.pub-cache/hosted/pub.dartlang.org/cloud_firestore-0.9.7+2/lib/src/firestore.dart:114:10)
<asynchronous suspension>
#3 _HomePageState._buildListItem.<anonymous closure> (package:maas_app/pages/home_page.dart:204:43)
#4 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:513:14)
#5 _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:568:30)
#6 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:120:24)
#7 TapGestureRecognizer._checkUp (package:flutter/src/gestures/t<…>
На самом деле он отлично обновляется на бэкенде и правильно отображается на моем симуляторе. Но я явно что-то здесь упускаю. Я не уверен, почему он получает эту ошибку, так как все операторы печати, которые я пробовал, не показывают нулевые объекты / ссылки.
Любая помощь очень ценится !!!
Перед печатью onTap:
flutter: Todo{subject: make flutter awesome, completed: false, userId: test@test.com, reference: Instance of 'DocumentReference'}
После печати onTap:
flutter: Todo{subject: make flutter awesome, completed: true, userId: test@test.com, reference: Instance of 'DocumentReference'}
Я пробовал разные варианты транзакции. Обновление, которое я видел в https://codelabs.developers.google.com/codelabs/flutter-firebase/index.html#10 и https://medium.com/flutter-community/simple-recipes-app-made-in-flutter-firestore-f386722102da
Оба корректно выполняют обновление в Firestore и UI, но выдают одно и то же исключение.
В разделе onTap происходит сбой:
Widget _buildListItem(BuildContext context, DocumentSnapshot data) {
final todo = Todo.fromSnapshot(data);
print(todo);
return Padding(
key: ValueKey(todo.toString()),
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(todo.subject),
trailing: Text(todo.completed.toString()),
onTap: () => Firestore.instance.runTransaction((Transaction transaction) async {
final DocumentSnapshot freshSnapshot = await transaction.get(todo.reference);
final Todo fresh = Todo.fromSnapshot(freshSnapshot);
await transaction.update(todo.reference, {'completed': !fresh.completed});
}),
),
),
);
}
Моя модель Todo:
import 'package:cloud_firestore/cloud_firestore.dart';
class Todo {
final String subject;
final bool completed;
final String userId;
final DocumentReference reference;
Todo.fromMap(Map<String, dynamic> map, {this.reference})
: assert(map['userId'] != null),
assert(map['subject'] != null),
assert(map['completed'] != null),
userId = map['userId'],
subject = map['subject'],
completed = map['completed'];
Todo.fromSnapshot(DocumentSnapshot snapshot)
: this.fromMap(snapshot.data, reference: snapshot.reference);
@override
String toString() {
return 'Todo{subject: $subject, completed: $completed, userId: $userId, reference: $reference}';
}
}
ОБНОВЛЕНИЕ: Пробное обновление даже без использования моделей с заходом на посадку с https://www.youtube.com/watch?v=DqJ_KjFzL9I. По-прежнему получаю ту же ошибку: (
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class TodoListWidget extends StatelessWidget {
TodoListWidget({this.firestore});
final Firestore firestore;
@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: firestore.collection('todo').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return const Text('Loading...');
final int messageCount = snapshot.data.documents.length;
return ListView.builder(
itemCount: messageCount,
itemBuilder: (_, int index) {
final DocumentSnapshot document = snapshot.data.documents[index];
return ListTile(
title: Text(document['subject'] ?? '<No subject retrieved>'),
trailing: Text(document['completed']?.toString() ?? '<No completed retrieved>'),
onTap: () => Firestore.instance.runTransaction((Transaction transaction) async {
final DocumentSnapshot freshSnapshot = await transaction.get(document.reference);
await transaction.update(freshSnapshot.reference, {
'completed': !freshSnapshot.data['completed'],});
}),
);
},
);
},
);
}
}