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
объекты не могут удалить слушателей после их добавления).