Значение моей переменной изменяется после второго нажатия кнопки. - PullRequest
0 голосов
/ 26 декабря 2018

Я пытаюсь обновлять переменную каждый раз, когда нажимаю кнопку в базе данных Firestore, но проблема в том, что при каждом запуске приложения в первый раз, когда я нажимаю кнопку,во второй раз он работает правильно .

кажется, что моя переменная не инициализируется правильно при первом нажатии моей кнопки.Я не знаю точно.

private String name;
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.friendsystem_add);


    //[Initializing UI Components]
    emailToAdd = findViewById(R.id.friend_rq_name);


    //[Getting variable]
    Button send = findViewById(R.id.friend_rq_send);
    send.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            final String email = emailToAdd.getText().toString();
            //check if user exists or not
            doesExist(email);

        }

    Toast.makeText(AddFriend.this, name, Toast.LENGTH_SHORT).show();

и это мой метод:

    private void doesExist(String email) {
    //sending our friend request to database

    db.collection("Users")
            //query
            .whereEqualTo("email", email)
            //getting results
            .get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    //check if task is successfull
                    if (task.isSuccessful()) {
                        for (QueryDocumentSnapshot document : task.getResult()) {

                            //getting target account name
                            name = document.getString("name");

                        }
                    }
                }
            });
}

Вот мой полный код: https://gist.github.com/arshiyanine/dc16f187d5bcaaaefddd8e38fd8f82c1 Спасибо.

1 Ответ

0 голосов
/ 26 декабря 2018

Данные загружаются из Cloud Firestore асинхронно, и код после начала загрузки продолжает выполняться.Затем, когда данные загружены, SDK вызывает ваш обработчик завершения.Это означает, что данные доступны только внутри метода onComplete.Чтобы увидеть, что это значит, запустите ваш код с помощью нескольких операторов журнала, таких как:

System.out.println("Before starting query");
db.collection("Users")
  .whereEqualTo("email", email)
  .get()
  .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
      @Override
      public void onComplete(@NonNull Task<QuerySnapshot> task) {
          System.out.println("Got documents");
      }
  });
System.out.println("After starting query");

Если вы запустите этот код, вы получите:

Перед запуском запроса

После запуска запроса

Получил документы

Вероятно, это не тот порядок, который вы ожидали.Но это прекрасно объясняет, почему тост не отображает имя из базы данных: данные еще не загружены!

Это означает, что любой код, которому нужны данные из базы данных, должен быть (вызван из) внутри метод onComplete().Самое простое решение - просто отобразить тост в этом методе:

private void doesExist(String email) {
    db.collection("Users")
      .whereEqualTo("email", email)
      .get()
      .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
          @Override
          public void onComplete(@NonNull Task<QuerySnapshot> task) {
              if (task.isSuccessful()) {
                  for (QueryDocumentSnapshot document : task.getResult()) {
                      name = document.getString("name");
                  }
                  Toast.makeText(AddFriend.this, name, Toast.LENGTH_SHORT).show();
              }
          }
      });
}

Это очень просто, но делает ваш doesExist менее пригодным для повторного использования.Если это проблема, подумайте о создании пользовательского обратного вызова;похож на Task, но затем посвящен вашему варианту использования здесь.Простой пример этого:

public interface GetUserNameCallback {
  void onUserExists(String name);
  void onUserDoesNotExist();
}
private void doesExist(String email, UserExistsCallback callback) {
    db.collection("Users")
      .whereEqualTo("email", email)
      .get()
      .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
          @Override
          public void onComplete(@NonNull Task<QuerySnapshot> task) {
              if (task.isSuccessful()) {
                  String name;
                  for (QueryDocumentSnapshot document : task.getResult()) {
                      name = document.getString("name");
                  }
                  callback.onUserExists(name);
              }
              else {
                  callback.onUserDoesNotExist();
              }
          }
      });
}

И затем вызовите его следующим образом:

doesExist(email, new UserExistsCallback() {
  @Override
  public void onUserExists(String name) {
    Toast.makeText(AddFriend.this, name, Toast.LENGTH_SHORT).show();
  }
  @Override
  public void onUserDoesNotExist() {
    Toast.makeText(AddFriend.this, "User "+email+" does not exist", Toast.LENGTH_SHORT).show();
  }
});

Дополнительные примеры этого см .:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...