Android中Firestore读取后ArrayList为空 无法校验昵称重复问题求助
问题根源
空列表问题是Firestore 异步执行机制导致的:
addSnapshotListener属于异步回调接口,调用后不会阻塞当前主线程,会立刻返回,主线程会继续向下执行你写的昵称校验逻辑- 此时 Firestore 还未完成远程数据拉取,
onEvent回调中给nicklist添加数据的代码还没执行,所以判断时列表必然是空的
优化修正方案
- 单次校验昵称不需要使用实时监听
addSnapshotListener,改用get()做单次请求即可,避免重复注册监听导致内存泄漏 - 所有昵称校验、数据写入、页面跳转的逻辑必须放到数据请求成功的回调内部执行,保证执行校验时已经拿到全量的已存在昵称列表
- 不需要将
nicklist设为全局变量,每次校验时在回调内创建新列表即可,避免旧缓存数据导致校验错误
修改后的核心代码
public void kayıt(View view) { String nick = nickText.getText().toString(); // 先做非空校验 if (nick.trim().isEmpty()) { Toast.makeText(this, "请输入有效昵称", Toast.LENGTH_SHORT).show(); return; } CollectionReference collectionReference = firestore.collection("Kullanıcılar ve Skorlar"); // 单次请求获取所有昵称数据 collectionReference.get().addOnCompleteListener(task -> { if (task.isSuccessful()) { ArrayList<String> nickList = new ArrayList<>(); for (QueryDocumentSnapshot doc : task.getResult()) { String existNick = doc.getString("nick"); if (existNick != null) { nickList.add(existNick); } } // 校验逻辑放到回调内执行 if (nickList.contains(nick)) { Toast.makeText(NickName.this, "Bu Kullanıcı İsmi Zaten Mevcut", Toast.LENGTH_SHORT).show(); } else { userid = mAuth.getCurrentUser().getUid(); DocumentReference documentReference = firestore.collection("Kullanıcılar ve Skorlar").document(userid); Map<String, Object> userData = new HashMap<>(); userData.put("nick", nick); userData.put("email", email); userData.put("skor", 0); documentReference.set(userData) .addOnSuccessListener(unused -> Log.d("Tag", "Veri alındı" + userid)) .addOnFailureListener(e -> Log.d("Tag", "işlem başarısız" + e.toString())); Intent intent = new Intent(NickName.this, Secimekrani.class); startActivity(intent); finish(); } } else { Log.e("tag", "数据拉取失败", task.getException()); Toast.makeText(NickName.this, "网络请求失败,请重试", Toast.LENGTH_SHORT).show(); } }); }
内容的提问来源于stack exchange,提问作者Yusuf Aydın
相关产品推荐
相关产品推荐

