Firebase API和Android的活动生命周期

时间:2018-04-27 21:12:46

标签: android firebase android-activity callback android-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对象的侦听器),始终直接在活动或片段中编码。

对于iOS和Web编程,这种基于回调的API非常好用。这对Android来说也不错,除了它似乎与谷歌自己处理活动(和片段)生命周期的指导相反。具体而言,对delete()signOut()等API方法的调用是异步操作的。作为侦听器传递的回调对象将保留,直到关联的任务完成并调用回调。如果活动(或片段)被销毁,然后在任务执行时重新创建(例如,通过配置更改),则将在陈旧对象上调用回调。回调还保留对被破坏活动的引用,导致内存泄漏。

我们如何处理这些回调?对于观察查询,Google建议使用LiveData个对象(如this blog post中所述)。但是,对于许多Firebase任务(例如上面的两个示例),使用LiveData没有多大意义。我们是否应该在保留的片段或服务中编写所有这些调用?这似乎不太可行。另一方面,也许这是唯一合理的事情(考虑到Task个对象在添加后没有任何方法可以删除它们。)

1 个答案:

答案 0 :(得分:2)

使用Task API时,如果您的工作应该绑定到Activity的生命周期,那么您应该使用接受Activity参数的addOnCompleteListener,addOnSuccessListener和addOnFailureListener的activity-scoped overloads第一个参数。执行此操作时,将在活动停止时自动删除回调,并且回调对象不会泄漏(除非您执行了其他错误操作)。

对于我所知道的大多数任务实现,添加和删除这样的侦听器几乎没有成本,因为SDK实际上不会通过内部缓存结果来复制工作。

如果您的工作确实必须不断地听取结果,或者您不相信SDK在添加自动删除侦听器时做正确的事情,那么来自架构组件的LiveData可以帮助保留跨生命周期的工作变化。