【发布时间】:2022-01-15 18:12:06
【问题描述】:
我目前正在开发一个与 Firebase 集成的 Android 项目,但是由于 Firebase 侦听器,我正在努力从 Firebase 实时数据库中检索一个类对象。
让我详细说明我的项目,以便您了解它的主要思想。我使用 MVVM 架构,我有 2 个活动,其中一个用于身份验证,另一个用于主要用途。
第一个活动包含注册、登录、密码重置片段 第二个活动包含 4 个片段,用于程序的主要功能
第一个活动中的片段使用共享视图模型“AuthViewModel”,其中包含调用 AuthRepository 对象方法的方法和为片段提供数据的 LiveData 变量
我所有的 Firebase Auth 操作都在这个 AuthRepository 的方法中处理,例如这是 AuthRepository 中的 register 方法,它使用 FireBase Auth 方法注册用户,同时通过创建一个 User 对象将用户添加到实时数据库中。
public void register(String email , String pass, String username, String department){
auth.createUserWithEmailAndPassword(email , pass).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()){
firebaseUserMutableLiveData.postValue(auth.getCurrentUser());
// Add user to realtime database
FirebaseUser user = auth.getCurrentUser();
dbRef.child("Users").child(user.getUid()).setValue(new User(email, username, department));
}
else{
Toast.makeText(application, task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
}
既然你有了主要的想法,让我们继续我的问题。就像 AuthRepository 一样,我有一个 MainRepository 作为变量添加到 MainViewModel 中,它是负责第二个活动中 4 个片段的 ViewModel。
无论我尝试了什么,我都无法检索相应用户的用户对象并将该对象分配给 MainRepository 类中的用户变量。
问题不在于检索数据,因为 “IN LISTENER:” Toast 在实时数据库中显示正确的用户对象
但是 "OUT LISTENER: " 和 "FINAL: " Toast 显示了在侦听器之外初始化的 User 对象。我不知道为什么,但侦听器中的用户对象似乎是类中用户对象的副本,即使它们共享相同的哈希码,如果我没有在 firebase 中为用户对象分配用户对象。
尽管进行了长时间的搜索,但我无法从内部类访问外部类的“真实”对象“不是副本”。即使我似乎正在访问和调用外部对象的方法,它们也不会持续存在于侦听器之外。
这里有什么问题,我能做些什么来解决它?如果无法解决,我应该怎么做呢?
不同的输出
Toast.makeText(application, "IN LISTENER: "+ user.hashCode() + user.getDepartment(), Toast.LENGTH_SHORT).show();
相同的输出
Toast.makeText(application, "OUT LISTENER: "+ user.hashCode() + user.getDepartment(), Toast.LENGTH_SHORT).show();
Toast.makeText(application, "FINAL: "+ user.hashCode() + user.getDepartment(), Toast.LENGTH_SHORT).show();
public class MainRepository {
private Application application;
private FirebaseAuth auth;
private DatabaseReference dbRef;
private MutableLiveData<User> userMutableLiveData;
private User user;
public MainRepository(Application application) {
this.application = application;
auth = FirebaseAuth.getInstance();
dbRef = FirebaseDatabase.getInstance().getReference();
getUser();
Toast.makeText(application, "FINAL: " + user.hashCode() + user.getDepartment(), Toast.LENGTH_SHORT).show();
}
class ListenerInner implements ValueEventListener {
MainRepository mainRepository;
ListenerInner(MainRepository mainRepository) {
this.mainRepository = mainRepository;
}
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
mainRepository.setUser(snapshot.getValue(User.class));
Toast.makeText(application, "IN LISTENER: "+ user.hashCode() + user.getDepartment(), Toast.LENGTH_SHORT).show();
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Toast.makeText(application, "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
}
}
public void getUser() {
setUser(new User("aaa", "bbb", "ccc"));
dbRef.child("Users").child(auth.getCurrentUser().getUid()).addListenerForSingleValueEvent(new ListenerInner(this));
Toast.makeText(application, "OUT LISTENER: " + user.hashCode() + user.getDepartment(), Toast.LENGTH_SHORT).show();
}
private void setUser(User user) {
this.user = user;
}
}
【问题讨论】:
标签: java android firebase firebase-realtime-database inner-classes