İbrahim
İbrahim

Reputation: 1021

Android Firebase: How is OnCompleteListener working asynchronously if it called on main application thread?

I've written a code to create a new account using Firebase Auth:

public static int signUp(String email, String password) {
  mAuth.createUserWithEmailAndPassword(email, password)
      .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
        @Override
        public void onComplete(@NonNull Task<AuthResult> task) {
          if (task.isSuccessful()) {
            Log.i("accountMessage", "User has registered successfully!");
          } else {
            try {
              throw task.getException();
            } catch (FirebaseAuthUserCollisionException e) {
              Log.i("accountMessage", "User is registered already!");
            } catch (Exception e) {
              e.printStackTrace();
            }
          }
        }
      });

  Log.i("accountMessage", "I want that this message works lastest!");
}

I can catch accountMessages using LogCat. Normally I have to first see "User is registered already!" message but, I can't see it first: Android LogCat accountMessage I've seen on Google APIs for Android that OnCompleteListener called on main application thread, but I cannot understand that if OnCompleteListener called on main application thread (I know that main application thread is same UI Thread on Android), how is it working as asynchronously? Shouldn't it work synchronously if it is working on the main application thread? I mean shouldn't we see first "User is registered already!", then "I want that this message works lastest!" message? Is there a way for OnCompleteListener works on UI Thread as synchronously if is it working as asynchronously?


Edit 2:

In fact, the asynchronously operation of the onComplete causes the res[0] in the following code to return from the signUp method before it is given the value in the onComplete:

public static int signUp(String email, String password) {
  final int[] res = new int[1];
  mAuth.createUserWithEmailAndPassword(email, password)
      .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
        @Override
        public void onComplete(@NonNull Task<AuthResult> task) {
          if (task.isSuccessful()) {

            res[0] = 123;

            // We can't use 'return 123;' in here...

          }
        }
      });

  // You can see that value of res[0] is "0", because not given "123" value.
  // Must be: First, given "123" value to res[0], after then return res[0];
  return res[0];
}

Upvotes: 1

Views: 1838

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 599051

The work happens off the main thread, so that it doesn't block you app. The onComplete callback is then scheduled onto the main thread, so that you update the UI without having to do the context switch yourself.

Upvotes: 2

Related Questions