首先,如果标题误导我,我深表歉意。英语不是我的母语,所以我不确定该如何命名。现在的问题是:
我有一个活动,可显示存储在Firebase项目中有关用户的数据。数据在Firebase用户(显示名称,电子邮件和个人资料图像)和Cloud
Firestore中名为该用户的文档之间分配UID
。
当此活动开始时,我进行了Firebase谷歌身份验证以获取用户,然后出现了问题。我需要知道用户是否在数据库中有一个链接文档及其附加数据(现有用户),或者他是否需要创建一个链接文档(新用户)。我创建了一种方法来检查是否存在像用户的UID这样的文档。这是方法:
public void userExists(String uid) {
FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference docRef = db.collection("users").document(uid);
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot documentSnapshot = task.getResult();
if (documentSnapshot.exists()) {
aa = true;
aa=true;
} else {
aa = false;
}
} else {
aa = false;
}
}
});
}
(aa
是在Activity中声明的布尔变量)。
我在下一个方法中调用此方法,以了解是否需要启动新的Activity来创建文档,或者是否可以在当前Activity中显示用户数据而不会出现问题。
private void updateUI(FirebaseUser user) {
if (user != null) {
userExists(user.getUid());
if(aa){
//Fill layout with the user data and the user linked document data
//USER DATA
txvNombre=findViewById(R.id.nombrePerfil);
txvNombre.setText(user.getDisplayName());
imvAvatar=findViewById(R.id.imvVistaPerfilAvatar);
Picasso.with(VistaPerfilActivity.this)
.load(user.getPhotoUrl())
.resize(500,500)
.centerCrop()
.into(imvAvatar);
//HERE GOES THE DOCUMENT DATA
}else{
}
} else {
finish();
}
}
据我所知,Firestore连接是在新线程中建立的,因此,当UpdateUI(FirebaseUser
user)启动时,aa
始终为false,因为userExists(String uid)尚未完成。userExists(String
uid)正常工作,我已经检查了它。
因此,我需要知道如何检查Firestore连接线程是否完成,才能继续执行该应用程序。我尝试使用OnCompleteListener(如代码中所示),但是它不起作用。我也尝试只在userExists(String
uid)方法中编写操作,而不是仅更改aa的值,然后继续使用另一种方法,但是我得到了
从内部类内部访问变量需要声明为final
错误。我试图遵循Android Studio的建议,将变量定为final,但是由于明显的原因,我无法使用它。
提前致谢。
问题不是由多线程引起的,而是由Firebase异步加载数据引起的。等到您的updateUI
函数查看的值时aa
,onComplete
尚未运行。
通过放置一些放置良好的日志记录语句,这最容易看到:
System.out.println("Before attaching listener");
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
System.out.println("Got document");
}
});
System.out.println("After attaching listener");
当您运行此代码时,它会打印
附加监听器之前
附加监听器后
得到文件
这可能不是您所期望的,但恰恰说明了检查aa
时为什么未修改的原因updateUI
。该文件尚未从Firestore中读取,因此onComplete
尚未运行。
此解决方案是移动从数据库中需要的数据的所有码 成 的onComplete
方法。在这种情况下,最简单的方法是:
public void userExists(String uid) {
FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference docRef = db.collection("users").document(uid);
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot documentSnapshot = task.getResult();
if (documentSnapshot.exists()) {
//Fill layout with the user data and the user linked document data
//USER DATA
txvNombre=findViewById(R.id.nombrePerfil);
txvNombre.setText(user.getDisplayName());
imvAvatar=findViewById(R.id.imvVistaPerfilAvatar);
Picasso.with(VistaPerfilActivity.this)
.load(user.getPhotoUrl())
.resize(500,500)
.centerCrop()
.into(imvAvatar);
//HERE GOES THE DOCUMENT DATA
}
}
}
});
}
现在,需要文档的代码仅在文档实际可用后才运行。这将起作用,但是确实会使该userExists
函数的可重用性降低。如果要解决此问题,可以将回调传递
到 userExists
该回调中,然后在加载文档后调用该回调。
public interface UserExistsCallback {
void onCallback(boolean isExisting);
}
并将其userExists
用作:
public void userExists(String uid, final UserExistsCallback callback) {
FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference docRef = db.collection("users").document(uid);
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
boolean userExists = false;
if (task.isSuccessful()) {
DocumentSnapshot documentSnapshot = task.getResult();
userExists = documentSnapshot.exists();
}
callback.onCallback(userExists);
}
});
}
然后使用以下命令调用它updateUI
:
if (user != null) {
userExists(user.getUid(), new UserExistsCallback() {
public void onCallback(boolean isExisting) {
if(isExisting){
//Fill layout with the user data and the user linked document data
//USER DATA
txvNombre=findViewById(R.id.nombrePerfil);
txvNombre.setText(user.getDisplayName());
imvAvatar=findViewById(R.id.imvVistaPerfilAvatar);
Picasso.with(VistaPerfilActivity.this)
.load(user.getPhotoUrl())
.resize(500,500)
.centerCrop()
.into(imvAvatar);
//HERE GOES THE DOCUMENT DATA
}else{
}
} else {
finish();
}
});
}
如您所见,我们的`回调与
OnCompleteListener`Firestore本身非常相似,它只是针对我们的需求量身定制了。
我在Ubuntu 14.04中使用XAMPP for linux。在终端上启动服务时,打印下一个日志: sudo /opt/lampp/lampp启动 "开始XAMPPLinux5.5.30-0... XAMPP:正在启动Apache。。。好啊 XAMPP:正在启动MySQL。。。已经在运行了。 XAMPP:开始ProFTPD...好的。" 我不知道为什么当我第一次启动XAMPPm时,MySQL服
我试图在包含GUI系统的JDK 11.0.2上运行我在Intellij中创建的一个可执行jar文件。我已经安装了Java8和java SDK11.0.2。每当我双击jar文件时,我希望主gui登录屏幕出现,但什么也没有发生。我已经尝试了其他选项,例如尝试通过cmd运行它(它给了我一个访问错误),HKEY_CLASSES_ROOT\jarfile已经有命令:“C:\Program Files\jav
我正在尝试让nutch 1.11执行爬网。我正在使用cygwin在windows 7中运行这些命令。 Nutch正在运行,运行bin/Nutch会得到结果,但当我尝试运行爬网时,会不断收到错误消息。 当我尝试使用 nutch 运行爬网执行时,我收到以下错误: 运行时出错:/cygdrive/c/Users/User5/Documents/Nutch/apache-Nutch-1.11/runtim
我有一个IP地址每次我收到连接失败的消息时,我都尝试了很多连接到该服务器的方法。出于安全原因,我隐藏了用户名和密码。 代码: 我有例外 组织。postgresql。util。PSQLException:连接尝试失败。在org。postgresql。果心v3。连接工厂impl。org上的openConnectionImpl(ConnectionFactoryImpl.java:292)。postgr
我还是nodejs的新手,有些东西不能理解。我有带有代码的db.js文件: 当我尝试这样插入行时: 它会失败,并出现sql语法错误。为什么它失败了,它工作得很好,只是使用了稍微不同的db.js。我在这里寻找简短而正确的解决方案。
我们正在尝试将涡轮机集成到我们的应用程序中。 我下载了1。o、 o样品发布(https://github.com/spring-cloud-samples/turbine/releases/tag/v1.0.0.RELEASE)建造并运行它。我没有连接到eureka(我拥有的其他服务与应用程序yml connect fine中的eureka连接设置相同)。 考虑到也许我应该尝试最新版本的turbi