Firebase API 和 Android 的 activity 生命周期
Firebase API and Android's activity lifecycle
Firebase API 是围绕回调架构设计的。它充满了类似这个 Firestore 示例的结构(取自 here):
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 身份验证示例(来自 here):
AuthUI.getInstance()
.signOut(this)
.addOnCompleteListener(new OnCompleteListener<Void>() {
public void onComplete(@NonNull Task<Void> task) {
// ...
}
});
Google 自己的示例代码和应用程序充满了此类回调(通常作为侦听器分配给 Task
对象),总是直接编码在 activity 或片段中。
对于iOS和web编程来说,这种基于回调的API真的很不错。这对 Android 也很好,除了它似乎与 Google 自己关于处理 activity(和片段)生命周期的指南相反。具体来说,对 API 方法(如 delete()
或 signOut()
的调用是异步操作的。作为侦听器传递的回调对象将被保留,直到关联的任务完成并调用回调。如果 activity(或片段)在任务执行时被销毁然后重新创建(例如,通过配置更改),则将在陈旧对象上调用回调。回调还保留对已销毁 activity 的引用,导致内存泄漏。
我们应该如何处理这些回调?对于观察查询,Google 建议使用 LiveData
对象(如 this blog post)。但是,对于许多 Firebase 任务(例如上面的两个示例),使用 LiveData
没有多大意义。我们是否应该将所有这些调用编码在保留的片段或服务中?这似乎不太可行。另一方面,也许这是唯一合理的做法(考虑到 Task
对象在添加后无法删除侦听器)。
当使用接受 Activity 参数作为第一个参数的 addOnCompleteListener、addOnSuccessListener 和 addOnFailureListener 的 Task API, if you have work that should be bound to the lifecycle of an Activity, you should be using the activity-scoped overloads 时。当你这样做时,回调将在 activity 停止时自动删除,并且回调对象不会泄漏(除非你做错了什么)。
对于我所知道的大多数任务实现,像这样添加和删除侦听器几乎没有成本,因为 SDK 不会通过在内部缓存结果有效地重复工作。
如果您的工作确实必须持续监听以获得结果,或者您不相信 SDK 在添加自动删除监听器时会做正确的事情,那么 LiveData 来自架构组件可以帮助保留跨生命周期变更的工作。
Firebase API 是围绕回调架构设计的。它充满了类似这个 Firestore 示例的结构(取自 here):
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 身份验证示例(来自 here):
AuthUI.getInstance()
.signOut(this)
.addOnCompleteListener(new OnCompleteListener<Void>() {
public void onComplete(@NonNull Task<Void> task) {
// ...
}
});
Google 自己的示例代码和应用程序充满了此类回调(通常作为侦听器分配给 Task
对象),总是直接编码在 activity 或片段中。
对于iOS和web编程来说,这种基于回调的API真的很不错。这对 Android 也很好,除了它似乎与 Google 自己关于处理 activity(和片段)生命周期的指南相反。具体来说,对 API 方法(如 delete()
或 signOut()
的调用是异步操作的。作为侦听器传递的回调对象将被保留,直到关联的任务完成并调用回调。如果 activity(或片段)在任务执行时被销毁然后重新创建(例如,通过配置更改),则将在陈旧对象上调用回调。回调还保留对已销毁 activity 的引用,导致内存泄漏。
我们应该如何处理这些回调?对于观察查询,Google 建议使用 LiveData
对象(如 this blog post)。但是,对于许多 Firebase 任务(例如上面的两个示例),使用 LiveData
没有多大意义。我们是否应该将所有这些调用编码在保留的片段或服务中?这似乎不太可行。另一方面,也许这是唯一合理的做法(考虑到 Task
对象在添加后无法删除侦听器)。
当使用接受 Activity 参数作为第一个参数的 addOnCompleteListener、addOnSuccessListener 和 addOnFailureListener 的 Task API, if you have work that should be bound to the lifecycle of an Activity, you should be using the activity-scoped overloads 时。当你这样做时,回调将在 activity 停止时自动删除,并且回调对象不会泄漏(除非你做错了什么)。
对于我所知道的大多数任务实现,像这样添加和删除侦听器几乎没有成本,因为 SDK 不会通过在内部缓存结果有效地重复工作。
如果您的工作确实必须持续监听以获得结果,或者您不相信 SDK 在添加自动删除监听器时会做正确的事情,那么 LiveData 来自架构组件可以帮助保留跨生命周期变更的工作。