I'm building an app and trying to fetch data immediately after the user presses a button. However, the data fetching part isn't happening until the onClickListener's onComplete is over. I need access to the data before onComplete is over.
Right now, my fragment contains an e-mail and password field, which they fill up and press "Login" button. I have set an onClickListener
on the Login button inside which FirebaseAuth's
signInWithEmailandPassword
method is called. This returns an AuthResult Task, which I set an onCompleteListener to.
If this Task is successful, I trigger an addListenerForSingleValueEvent()
task to fetch the relevant user's data from Firebase realtime database. It seems that this task runs after the onComplete method. How do I change that? I tried using AsyncTask for this but the result was the same.
my LoginFragment:
mLogInButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
String email = mEmailText.getText().toString();
String password = mPasswordText.getText().toString();
final boolean[] loginSuccess = {false};
Task task = mViewModel.signIn(email,
password).addOnCompleteListener
(new OnCompleteListener() {
@Override
public void onComplete(@NonNull Task task) {
if (task.isSuccessful()) {
Log.d(TAG, "signInWithEmail:success");
Toast.makeText(getActivity(),
"Signed in!",
Toast.LENGTH_SHORT).show();
loginSuccess[0] = true;
String uid = mViewModel.getAuth().getUid();
mViewModel.fetchUser(uid);
Log.d(TAG, mViewModel.getUser().getName());
} else {
Log.w(TAG, "signInWithEmail:failure",
task.getException());
Toast.makeText(getActivity(), "Auth failed.
Check log!",
Toast.LENGTH_SHORT).show();
loginSuccess[0] = false;
}
}
});
//Task fetchDatabase = task.addOnCompleteListener(new
//OnCompleteListener() {
//@Override
//public void onComplete(@NonNull Task task) {
// Log.d(TAG, "After!");
// }
//});
// updateUIWithDatabaseDetails(mView);
}
});
my fetchUser(uid) and its associated ValueEventListener:
public void fetchUser(String uid) {
mUserDatabase.child(uid).addListenerForSingleValueEvent(userDataValueListener);
}
public ValueEventListener userDataValueListener = new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Log.d(TAG, "User exists in remote!");
mUser = dataSnapshot.getValue(User.class);
}
else {
Log.d(TAG, "user doesn't exist.");
mUser = null;
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Log.d(TAG, "Can't fetch Firebase Database user:" + databaseError.getMessage());
mUser = null;
}
};
The current setup immediately crashes with a NullPointerException at Log.d(TAG, mViewModel.getUser().getName());
because the database hasn't fetched the user and updated the user in the SharedViewModel yet.
Bottom line: I think the database fetch task gets queued to execute after onComplete on Login's onClick is over. Is there any way I can squeeze in this task while onComplete is running? I was thinking of using Handler to move it from the UI thread but I don't really understand it and really need some pointers for this.
Any help would be appreciated!