我有一个简单的 Android 应用程序,其中使用 Firebase 实时数据库来存储登录用户的详细信息。
这是我存储在数据库中的用户对象:
public class User {
private UserType userType;
private String phoneNumber;
private String fullName;
private String email;
// addresses are stored as HOSTEL.ROOMNUMBER format
private String hostelAddress;
public User(UserType userType, String phoneNumber, String fullName, String email, String hostelAddress) {
this.userType = userType;
this.phoneNumber = phoneNumber;
this.fullName = fullName;
this.email = email;
this.hostelAddress = hostelAddress;
}
// required for realtime Database
public User() {
}
// getters and setters for all fields...
}
每次用户成功登录(通过 Firebase Auth 验证)时,我都会创建一个 User 对象,并将其存储为针对用户 UID 的值(作为数据库中的键)。到这部分为止的一切都按预期进行。
看起来像这样:
{
"users": {
"<UID>": {
"email": "<email>",
"fullName": "<full name>",
"hostelAddress": "<address>",
"phoneNumber": "<number>",
"userType": "CUSTOMER"
}
}
}
现在,我想要一个本地存储的用户对象,该对象与存储在与当前签名用户相对应的数据库中的用户对象同步。 我想在我的应用程序的不同活动中访问此用户对象。
为此,我创建了一个单独的类来与数据库交互:
abstract public class FirebaseUtil {
public static FirebaseDatabase database;
public static User currentUserObject;
public static String getCurrentUserID()
{
return FirebaseAuth.getInstance().getUid();
}
public static DatabaseReference getCurrentUserReference()
{
return database.getReference("users").child(getCurrentUserID());
}
static
{
database = FirebaseDatabase.getInstance();
fetchCurrentUser();
}
public static void fetchCurrentUser()
{
if (getCurrentUserID()==null)
{
return;
}
getCurrentUserReference().addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
currentUserObject = snapshot.getValue(User.class);
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
}
// Store user inside database, with the key as its UID.
public static void storeUser(User user, String UID)
{
database.getReference("users").child(UID).setValue(user).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
fetchCurrentUser();
}
});
}
}
问题是这种方法不起作用,每当我尝试在应用程序的另一个类中使用
currentUserObject
时,它总是null
,即使getCurrentUserID()
方法成功返回登录的用户UID。
我没有尝试过很多事情,因为我根本不知道为什么这不起作用。 我将感谢任何朝着正确方向的推动。
如果有更好、更可靠的方法来完成这项任务,请告诉我。
正如 @FrankvanPuffelen 在他的评论中已经提到的,这个问题很可能与 Firebase 加载数据的方式有关,这是异步的。我建议的是,不要在应用程序的每个活动中访问
fetchCurrentUser()
方法,只需在应用程序启动时创建对实时数据库的单个调用,等待读取数据的操作完成,将用户对象添加到意图并向前导航到另一个活动。
是的,永远不要忽视潜在的错误。因此,请务必通过抛出错误来检查
onCancelled()
方法内的错误消息:
throw databaseError.toException();
或者通过记录错误消息:
Log.d("TAG", error.getMessage());