Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/203.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Firestore,事务已完成_Java_Android_Firebase_Google Cloud Firestore - Fatal编程技术网

Java Firestore,事务已完成

Java Firestore,事务已完成,java,android,firebase,google-cloud-firestore,Java,Android,Firebase,Google Cloud Firestore,我有两个集合,“用户”和“用户名”。我想分别保存所有使用过的用户名和他关联的uid,这样我就可以快速访问它们,而不是查询成千上万的用户。它应该用于将来的用户名选择。为了防止用户使用与其他人相同的用户名,我想我将在一个事务中使用它,首先检查用户名是否存在,如果不存在,则添加用户名并更新“users”中的username属性。 这就是我到目前为止的情况: db.runTransaction(new Transaction.Function<Void>() { @Overr

我有两个集合,“用户”和“用户名”。我想分别保存所有使用过的用户名和他关联的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);
                }
            });
因此,我认为在我的查询进入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)

在我的场景中最好的方法是什么?

在这种情况下不需要使用事务。如果我们知道在我们的应用程序中,两个用户有可能在同一时间进行相同的
写入操作,那么我们将使用
事务。我们将使用事务,以便不同用户在同一时间进行的每一次写入都将在不同的执行线程中进行。这就是为什么我们使用事务来避免不一致的数据


在您的情况下,您只需要使用
get()
调用并使用
exists()
方法,就这样

但这正是问题所在?如果两个用户同时使用相同的名称注册会怎么样?这没问题,您只是在读取数据。Firebase在并发读取方面没有问题,只在写入方面有问题。但是,当用户想要添加用户名时,它会在集合“usernames”中使用其关联的uid写入文档。假设两个用户同时检查用户名是否存在,他们得到的答案是这些用户名可以自由使用。另一个人立即用他的uid写同一个文档。我不是失去了第一个用户吗?我想你误解了交易的概念。例如,在更新计数器时使用事务。看一看,以获得更好的理解。因此,作为对您评论的回答,事务用于允许用户在同一时间进行写操作,而不是限制他们,对吗?现在没事了,您明白了吗?
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)