Firebase API и жизненный цикл Android - PullRequest
0 голосов
/ 28 апреля 2018

Firebase API разработан на основе архитектуры обратного вызова. Он заполнен такими конструкциями, как этот пример Firestore (взят из здесь ):

db.collection("cities").document("DC")
        .delete()
        .addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                Log.d(TAG, "DocumentSnapshot successfully deleted!");
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Log.w(TAG, "Error deleting document", e);
            }
        });

или этот пример аутентификации Firebase (из здесь ):

AuthUI.getInstance()
    .signOut(this)
    .addOnCompleteListener(new OnCompleteListener<Void>() {
        public void onComplete(@NonNull Task<Void> task) {
            // ...
        }
    });

Собственный пример кода и приложений Google полон таких обратных вызовов (обычно назначаемых в качестве прослушивателей Task объектов), всегда закодированных непосредственно в деятельности или фрагменте.

Для iOS и веб-программирования такой API на основе обратного вызова действительно хорош. Это было бы неплохо и для Android, за исключением того, что, похоже, оно противоречит собственному руководству Google по работе с жизненными циклами активности (и фрагментов). В частности, вызовы методов API, таких как delete() или signOut(), работают асинхронно. Объекты обратного вызова, переданные в качестве прослушивателей, будут сохраняться до тех пор, пока не будет выполнена соответствующая задача и не будет вызван обратный вызов. Если действие (или фрагмент) будет уничтожено и затем воссоздано (скажем, путем изменения конфигурации) во время выполнения задачи, обратный вызов будет вызван для устаревшего объекта. Обратный вызов также сохраняет ссылку на уничтоженное действие, вызывая утечку памяти.

Как мы должны обрабатывать эти обратные вызовы? Для наблюдения за запросами Google предлагает использовать LiveData объектов (как в этом сообщении в блоге ). Однако для многих задач Firebase (таких как два примера выше) использование LiveData не имеет большого смысла. Должны ли мы просто кодировать все эти вызовы в сохраненных фрагментах или в сервисах? Это не кажется очень работоспособным. С другой стороны, возможно, это единственно разумная вещь (учитывая, что Task объекты не могут удалить слушателей после их добавления).

1 Ответ

0 голосов
/ 28 апреля 2018

При использовании Task API , если у вас есть работа, которая должна быть привязана к жизненному циклу действия, вы должны использовать перегрузки области действия addOnCompleteListener, addOnSuccessListener, и addOnFailureListener, которые принимают аргумент Activity в качестве первого параметра. Когда вы это сделаете, обратные вызовы будут автоматически удалены, когда действие остановлено, и объекты обратного вызова не будут просачиваться (если вы не сделали что-то еще неправильно).

Для большинства реализаций задач, о которых я знаю, добавление и удаление прослушивателей такого рода практически бесплатны, поскольку SDK эффективно не дублирует работу, кэшируя результаты внутри.

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

...