Получение данных из Firestore неустойчиво - PullRequest
0 голосов
/ 13 июля 2020

Я работаю над приложением Android, которое выполняет следующие функции:

  1. При запуске приложения оно проверяет, вошел ли пользователь в систему, используя AuthStateListener.
  2. Если есть авторизованный пользователь, он получает данные из Firestore. Пользовательские данные хранятся в документе, который я назвал по следующей номенклатуре: «Пользователь» + user_email_ID. Например, , если у пользователя есть электронный идентификатор xyz@gmail.com, его данные будут сохранены в документе с именем: User xyz@gmail.com. Все документы находятся в коллекции под названием «Пользователи».
  3. Если все поля в документе данных пользователя пустые / пустые, приложение открывает действие, которое просит его / ее заполнить все детали. В противном случае пользователь переходит на главную страницу (StudentMainActivity, если пользователь студент, или ProfessorMainActivity, если пользователь является профессором).

Переход к моей проблеме:

Блок кода, который проверяет, пусты ли поля, имеет некоторые ошибки c и непредсказуемое поведение. Я не уверен, связана ли это с проблемой Firestore или тем фактом, что получение данных происходит в другом потоке.

Я проверил базу данных Firestore и увидел, что все поля были заполнены. Однако, когда пользователь (который уже вошел в систему) запускает приложение, приложение знает, что это тот же пользователь (т. Е. Ему не предлагается войти в систему, потому что AuthStateListener выполняет свою работу), но вместо того, чтобы быть перенаправленным на StudentMainActivity или ProfessorMainActivity (главные экраны), его снова просят ввести свои данные.

Еще больше сбивает с толку то, что эта ошибка возникает не всегда. Бывают случаи, когда приложение делает то, что ожидается, то есть выводит пользователя на главный экран, но в следующий раз, когда он запускает приложение, он снова попадает в действие, которое просит его ввести свои данные.

Исходный код:

LoginActivity. java (Только соответствующие части)

    //AuthStateListener is in onCreate
    authStateListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
            FirebaseUser user = firebaseAuth.getCurrentUser();
            if (user != null){
                UIDEmailID = user.getEmail();
                updateUI(user);
            }
            else{
                updateUI(null);
            }
        }
    };

private void updateUI(FirebaseUser user){
    // Update UI after login
    if (user != null) {
        Toast.makeText(LoginActivity.this, "User " + UIDEmailID, Toast.LENGTH_LONG).show();
        db.collection("Users").document("User " + UIDEmailID).get()
                .addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                    @Override
                    public void onSuccess(DocumentSnapshot documentSnapshot) {
                        if (documentSnapshot.get("department") != null ||       // if any
                        documentSnapshot.get("phoneNumber") != null ||          // field in
                        documentSnapshot.get("name") != null ||                 // Firestore is
                        documentSnapshot.get("studentSemester") != null ||      // non-null then
                        documentSnapshot.get("dateOfBirth") != null ||          // proceed to
                        documentSnapshot.get("university") != null) {           // further activities
                            if (documentSnapshot.get("userType") == "Lecturer/ Professor") {
                                Intent intent = new Intent(LoginActivity.this, ProfessorMainActivity.class);
                                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                startActivity(intent);
                            }
                            else {
                                Intent intent = new Intent(LoginActivity.this, StudentMainActivity.class);
                                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                startActivity(intent);
                            }
                        } else {
                            Toast.makeText(LoginActivity.this, "We need some additional details before we go ahead.", Toast.LENGTH_SHORT).show();
                            Intent intent = new Intent(LoginActivity.this, GFBDetailsActivity.class);
                            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            startActivity(intent);
                        }
                    }
                }).addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Toast.makeText(LoginActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
                    }
                });
    }

}

Прошу прощения за длинный вопрос; Я просто попытался сделать его наглядным. Приветствуется некоторая помощь. экран), тост «Нам нужны дополнительные сведения, прежде чем мы go вперед». тоже появляется. Если вы посмотрите на код (последний блок «else»), вы поймете, что он находится в отдельном условном блоке и, следовательно, даже не должен отображаться, если на главном экране (который находится в другом условном блоке) отображается вверх.

РЕДАКТИРОВАТЬ 1:

Я прилагаю скриншоты, относящиеся к проблеме. Игнорируйте мягкий пользовательский интерфейс: P

This is what's expected (Comes under the second 'else' block). It is supposed to show up only if the user is logging in for the first time, i.e. does not have his data stored in a Firestore document.

Фон - это StudentMainActivity (внутри вложенного else). Однако отображается даже тост (он вообще принадлежит отдельному блоку).

1 Ответ

1 голос
/ 20 июля 2020

Получается, что Firestore не виноват (полностью).

Каждое действие в приложении Android имеет срок жизни, и каждый раз, когда действие запускается, оно проходит через сложную последовательность из функций жизненного цикла .

Жизненный цикл действия выглядит следующим образом:

Запущено -> onCreate () -> onStart () - > onResume () -> Running -> onPause () -> onStop () -> onDestroy () -> Finished

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

Как вы можете видеть во фрагменте кода в вопросе, onAuthStateChanged () находится внутри onCreate ( ). Мой идентификатор документа в Firebase имеет вид «Пользователь UIDEmailID », где UIDEmailID - это идентификатор электронной почты пользователя. И UIDEmailID обновляется только в onAuthStateChanged () (который, в свою очередь, находится внутри onCreate ()), т.е. только когда действие начинается сразу sh, после того, как приложение было закрыто и снова открыто.

Следовательно , Я также обновил UIDEmailID в onStart (), что означает, что каждый раз, когда приложение возобновляется, оно будет извлекать идентификатор электронной почты пользователя, который впоследствии может быть использован для получения документа из Firestore.

Также , Я немного изменил код для извлечения данных из Firestore по совету Nibrass H . Решение такое:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    running = true;
    if (savedInstanceState != null){
        running = savedInstanceState.getBoolean("running");
        wasrunning = savedInstanceState.getBoolean("wasrunning");
    }

    setContentView(R.layout.splash_screen);

    firebaseAuth = FirebaseAuth.getInstance();
    db = FirebaseFirestore.getInstance();

    authStateListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth1) {
            FirebaseUser user = firebaseAuth1.getCurrentUser();
            if (user != null){
                UIDEmailID = user.getEmail();
                updateUI(user);
            } else {
                updateUI(null);
            }
        }
    };
}

@Override
protected void onStart() {
    super.onStart();
    firebaseAuth.addAuthStateListener(authStateListener);
    if (firebaseAuth.getCurrentUser() != null) {
        UIDEmailID = firebaseAuth.getCurrentUser().getEmail();
        updateUI(firebaseAuth.getCurrentUser());
    } else {
        updateUI(null);
    }
}

@Override
protected void onRestart() {
    super.onRestart();
    authStateListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth1) {
            FirebaseUser user = firebaseAuth1.getCurrentUser();
            if (user != null) {
                UIDEmailID = user.getEmail();
                updateUI(user);
            } else {
                updateUI(null);
            }
        }
    };
}

@Override
protected void onPause() {
    super.onPause();
    wasrunning = running;
    running = false;
}

@Override
protected void onResume() {
    super.onResume();
    if (wasrunning){
        running = true;
    }
}

@Override
protected void onStop() {
    super.onStop();
    if (authStateListener != null) {
        firebaseAuth.removeAuthStateListener(authStateListener);
    }
}

private void updateUI(FirebaseUser firebaseUser){
    if (firebaseUser != null){
        Toast.makeText(this, "User " + firebaseUser.getEmail(), Toast.LENGTH_SHORT).show();
        db.collection("Users").document("User " + UIDEmailID).get()
                .addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                    @Override
                    public void onSuccess(DocumentSnapshot documentSnapshot) {
                        if (documentSnapshot.get("userType") != null) {
                            if (documentSnapshot.get("userType").equals("Lecturer/ Professor")){
                                Intent intent = new Intent(SplashScreenActivity.this, ProfessorMainActivity.class);
                                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                finish();
                                startActivity(intent);
                            } else {
                                Intent intent = new Intent(SplashScreenActivity.this, StudentMainActivity.class);
                                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                finish();
                                startActivity(intent);
                            }
                        } else {
                            Toast.makeText(SplashScreenActivity.this, "We need some additional details before we go ahead.", Toast.LENGTH_SHORT).show();
                            Intent intent = new Intent(SplashScreenActivity.this, GFBDetailsActivity.class);
                            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            finish();
                            startActivity(intent);
                        }
                    }
                });
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...