[英]Flutter/cloud-firestore “Task is already complete” Exception
I'm writing an app using Flutter and i have to make a transaction using the Firestore.instance.runTransaction(Transaction tx)
method. 我正在使用Flutter编写应用程序,我必须使用
Firestore.instance.runTransaction(Transaction tx)
方法进行Firestore.instance.runTransaction(Transaction tx)
。 In my Transaction object (or method) i have to update some data using the document reference. 在我的Transaction对象(或方法)中,我必须使用文档引用更新一些数据。
_firestore.runTransaction((Transaction x) async {
await x.update(Aref, {'data': itemA - y});
await x.update(Bref, {'data': itemB + y});
})
When the code is running it throw an exception (Here the console log): 代码运行时抛出异常(这里是控制台日志):
E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): Failed to handle method call result E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): java.lang.IllegalStateException: Task is already complete E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at com.google.android.gms.common.internal.Preconditions.checkState(Unknown Source:8) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at com.google.android.gms.tasks.zzu.zzdr(Unknown Source:8) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at com.google.android.gms.tasks.zzu.setResult(Unknown Source:3) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at com.google.android.gms.tasks.TaskCompletionSource.setResult(Unknown Source:2) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at io.flutter.plugins.firebase.cloudfirestore.CloudFirestorePlugin$3$1.success(CloudFirestorePlugin.java:283) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at io.flutter.plugin.common.MethodC
E / MethodChannel#plugins.flutter.io / cloud_firestore(32612):无法处理方法调用结果E / MethodChannel#plugins.flutter.io / cloud_firestore(32612):java.lang.IllegalStateException:任务已完成E / MethodChannel# plugins.flutter.io/cloud_firestore(32612):at com.google.android.gms.common.internal.Preconditions.checkState(Unknown来源:8)E / MethodChannel#plugins.flutter.io / cloud_firestore(32612):at com .google.android.gms.tasks.zzu.zzdr(未知来源:8)E / MethodChannel#plugins.flutter.io / cloud_firestore(32612):at com.google.android.gms.tasks.zzu.setResult(Unknown Source :3)E / MethodChannel#plugins.flutter.io / cloud_firestore(32612):at com.google.android.gms.tasks.TaskCompletionSource.setResult(Unknown来源:2)E / MethodChannel#plugins.flutter.io / cloud_firestore( 32612):at io.flutter.plugins.firebase.cloudfirestore.CloudFirestorePlugin $ 3 $ 1.success(CloudFirestorePlugin.java:283)E / MethodChannel#plugins.flutter.io / cloud_firestore(32612):at io.flutter.plugin.common。 MethodC hannel$IncomingResultHandler.reply(MethodChannel.java:169) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at io.flutter.view.FlutterNativeView.handlePlatformMessageResponse(FlutterNativeView.java:187) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at android.os.MessageQueue.nativePollOnce(Native Method) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at android.os.MessageQueue.next(MessageQueue.java:325) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at android.os.Looper.loop(Looper.java:142)
hannel $ IncomingResultHandler.reply(MethodChannel.java:169)E / MethodChannel#plugins.flutter.io / cloud_firestore(32612):at io.flutter.view.FlutterNativeView.handlePlatformMessageResponse(FlutterNativeView.java:187)E / MethodChannel#plugins。 flutter.io/cloud_firestore(32612):在android.os.MessageQueue.nativePollOnce(Native Method)E / MethodChannel#plugins.flutter.io / cloud_firestore(32612):at android.os.MessageQueue.next(MessageQueue.java:325 )E / MethodChannel#plugins.flutter.io / cloud_firestore(32612):at android.os.Looper.loop(Looper.java:142)
The error happens when there are multiple call to the firestore api concurrently, you have to nest each funcion inside the "whenComplete(() {}" method of the previous function. This is the wrong code : 当同时多次调用firestore api时会发生错误,你必须将每个函数嵌套在前一个函数的“whenComplete((){}”方法中。这是错误的代码:
g.f.runTransaction((transaction) async {
DocumentSnapshot snap =
await transaction.get(/my code);
await transaction.update(/my code).whenComplete(() {});
});
g.f.runTransaction((transaction) async {
DocumentSnapshot freshSnap =
await transaction.get(/my code));
await transaction.update(/my code).whenComplete(() {});
}); //here is the problem!! I'have to nest this inside "whenComplete(() {})
this is the error: 这是错误:
E/MethodChannel#plugins.flutter.io/cloud_firestore( 5337): Failed to handle method call result E/MethodChannel#plugins.flutter.io/cloud_firestore( 5337): java.lang.IllegalStateException: Task is already complete
E / MethodChannel#plugins.flutter.io / cloud_firestore(5337):无法处理方法调用结果E / MethodChannel#plugins.flutter.io / cloud_firestore(5337):java.lang.IllegalStateException:任务已完成
this is right code 这是正确的代码
g.f.runTransaction((transaction) async {
DocumentSnapshot snap =
await transaction.get(/my code);
await transaction.update(/my code).whenComplete(() {
g.f.runTransaction((transaction) async {
DocumentSnapshot freshSnap =
await transaction.get(/my code);
await transaction.update(/my code);
}).whenComplete(() {});
});
});
I had the same problem. 我有同样的问题。 Try this.
试试这个。 Hope it Helps FIrestore Transaction Handler
希望它有助于FIrestore事务处理程序
This is a subroutine to help handle the failing transaction issue when using runTransaction
function in cloud_firestore
pub for Flutter
这是一个子程序,用于在
cloud_firestore
pub中为Flutter
使用runTransaction
函数时帮助处理失败的事务问题
This code is a solution to errors with cloud_firestore package for Flutter for the following errors 1. PlatformException(Error performing Transaction#get, Transaction has already completed., null)
2. DoTransaction failed: Document version changed between two reads.
对于以下错误,此代码是针对Flutter的cloud_firestore包的错误的解决方案1.
PlatformException(Error performing Transaction#get, Transaction has already completed., null)
DoTransaction failed: Document version changed between two reads.
From my experience, I realized that the issue occurs when I try to update a record which was only just created. 根据我的经验,我意识到当我尝试更新刚刚创建的记录时会出现问题。 For some reason the
tx.get()
(see the example for runTransaction
in https://pub.dev/packages/cloud_firestore ) is unable to get the record that was just created and the update operation fails. 出于某种原因,
tx.get()
(请参阅https://pub.dev/packages/cloud_firestore中的 runTransaction
示例)无法获取刚刚创建的记录,并且更新操作失败。 I found that if we wait for a bit and try again, we will be able to get the record and update it. 我发现如果我们等一下再试一次,我们就能得到记录并更新它。 To make things easy, I have created a function that does the update and run transaction for you.
为了简单起见,我创建了一个为您执行更新和运行事务的函数。
Here is an example : 这是一个例子:
await fcmTransactionHandler(
postRef: postRef, // This is your DocumentReference that you want to update
key: 'myfield', // This is the field that you want to update
validationFunction: updateMyField, // This is a function that allows you to check
// some condition in the record you 'get' before updating
);
validationFunction
takes a dynamic value (value of the field you want to update) as input and gives the {}
value that you will update in the record. validationFunction
需要一个动态值(您想更新字段的值)作为输入,并给出了{}
值,您将在记录更新。 For example, if I want to update a field myfield
if it is say true
, then I will create a function updateMyField
as follows 例如,如果我想更新字段
myfield
如果它是true
,那么我将创建一个函数updateMyField
,如下所示
Map<String, dynamic> updateMyField({dynamic value}) {
return value ? <String, dynamic>{'myfield': true} : <String, dynamic>{'myfield': value};
}
Then this function is passed to validationFunction
. 然后将此函数传递给
validationFunction
。 Why is it designed like this ? 为什么这样设计? As you have seen, we are trying to get the record after a while and then update it.
如您所见,我们试图在一段时间后获取记录然后更新它。 What if the record has been updated by someone else in between ?
如果记录已经被其他人更新了怎么办? In that case, we have to validate the data we get when the record is available for us, to prevent any incorrect updates.
在这种情况下,我们必须验证记录可用时获得的数据,以防止任何不正确的更新。
validationFunction
helps us do that. validationFunction
帮助我们做到这一点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.