Firestore,Transaction已经完成

时间:2018-02-26 12:58:36

标签: java android firebase google-cloud-firestore

我收到了2个收藏集,“用户”和“用户名”。我想单独保存所有使用过的用户名及其关联的uid,因此我可以快速访问它们,而不是查询数千个用户。它应该用于将来的用户名选择。为了防止用户使用与其他人相同的用户名,我想我会在单个事务中进行,我首先检查用户名是否存在,如果不存在,我将其添加并更新“users”中的username属性。 那就是我到目前为止所拥有的:

db.runTransaction(new Transaction.Function<Void>() {
        @Override
        public Void apply(final Transaction transaction) throws FirebaseFirestoreException {

            db.collection("usernames").document(editTextUsername.getText().toString()).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
                @Override
                public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                    if (!task.getResult().exists()) {
                        transaction.update(sfDocRef, "username", editTextUsername.getText().toString());

                        Map<String, Object> usernameMap = new HashMap<>();
                        usernameMap.put("uid", FirebaseAuth.getInstance().getUid());

                        db.collection("usernames").document(editTextUsername.getText().toString()).set(usernameMap);
                    }
                }
            });

            return null;
        }
    }).addOnSuccessListener(new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void aVoid) {
            Log.d(TAG, "Transaction success!");
        }
    })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Log.w(TAG, "Transaction failure.", e);
                }
            });

如果我使用此代码运行我的应用程序,我会收到此异常

java.lang.IllegalStateException: Transaction has already completed.
 at com.google.android.gms.internal.zzeof.zzbb(Unknown Source)
 at com.google.android.gms.internal.zzeof.zza(Unknown Source)
 at com.google.firebase.firestore.Transaction.zza(Unknown Source)
 at com.google.firebase.firestore.Transaction.update(Unknown Source)
 at com.lala.rerere.ProfileAssistant.FragmentUsernameAsk$7$1.onComplete(FragmentUsernameAsk.java:179)
 at com.google.android.gms.tasks.zzf.run(Unknown Source)
 at android.os.Handler.handleCallback(Handler.java:751)
 at android.os.Handler.dispatchMessage(Handler.java:95)
 at android.os.Looper.loop(Looper.java:154)
 at android.app.ActivityThread.main(ActivityThread.java:6776)
 at java.lang.reflect.Method.invoke(Native Method)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

所以我认为事务在我的查询进入onCompleteListener之前返回 null ,可能是因为它是异步调用。现在我尝试在查询结束时添加getResult()。好吧,它奏效了!但是我收到了一个丑陋的警告

java.lang.IllegalStateException: Task is not yet complete
          at com.google.android.gms.common.internal.zzbq.zza(Unknown Source)
          at com.google.android.gms.tasks.zzn.zzbjk(Unknown Source)
          at com.google.android.gms.tasks.zzn.getResult(Unknown Source)
          at com.lala.rerere.ProfileAssistant.FragmentUsernameAsk$7.apply(FragmentUsernameAsk.java:181)
          at com.lala.rerere.ProfileAssistant.FragmentUsernameAsk$7.apply(FragmentUsernameAsk.java:165)
          at com.google.firebase.firestore.zzf.call(Unknown Source)
          at com.google.android.gms.tasks.zzo.run(Unknown Source)
          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
          at java.lang.Thread.run(Thread.java:762)

我的方案中最好的方法是什么?

1 个答案:

答案 0 :(得分:2)

在这种情况下无需使用交易。如果我们知道在我们的应用中,两个用户可以在同一时间内制作相同的transactions,我们会使用write operation。我们将使用事务,以便不同用户在同一时间进行的每次写入都可以在不同的执行线程中进行。这就是为什么我们使用事务来避免不一致的数据。

在您的情况下,您只需要使用get()来电并使用exists()方法即可!