第二次按下按钮后,变量值发生变化

时间:2018-12-26 19:29:59

标签: java android firebase google-cloud-firestore

每次尝试从Firestore数据库中按下按钮时,我都试图更新一个变量,但是问题是,每当我启动应用程序时,我第一次获得null时,当我按下按钮时,第二次正常工作

似乎我第一次按下按钮时变量未正确初始化。我不知道。

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 :(得分:0)

数据是从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();
  }
});

有关更多示例,请参见: