【问题标题】:Android - Firebase - Do I need to remove EVERY single listener?Android - Firebase - 我需要删除每个监听器吗?
【发布时间】:2016-09-11 03:22:38
【问题描述】:

我进行了合理的研究,但找不到我需要的答案。

我所知道的:当我将 ValueEventListener 附加到数据库引用时,我知道我需要稍后将其删除(现在很难通过大量内存泄漏找到它。

我不知道的事情:我还需要分离所有其他侦听器吗? (这包括 Firebase 数据库、存储和身份验证,我正在使用的三个 API)

例子:

UploadTask uploadTask = ref.putFile(uploadFile);

uploadTask.addOnFailureListener(new OnFailureListener() {
    //@Override code here
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TakeSnapshot>() {
    //@Override code here
}).addOnProgressListner(new OnProgressListner<UploadTask.TakeSnapshot>() {
    //@Override code here
};

我认为这足以说明我的意思。这就是我的实际代码目前的结构。

问题:

  1. 我是否需要删除所有这些侦听器以防万一活动 在此之前被终止(系统决定,电话死机等) 回调发生了吗?
  2. 我能否以某种方式将它们捆绑在一起并同时终止它们所有三个 因为我的代码中有 30 个这样的东西,而且真的不觉得 就像重组所有这些以便分配所有这些听众 到变量只是这样我就可以将它们传递给 “removeBlahBlahBlahListener(listenerVariable)”一遍又一遍。
  3. 有点跑题了,但是我懒得把我所有的代码都从 onCreate 到 onStart... 对我来说删除所有这些是不好的做法 听众,完成事情,调用finish()(或其他任何东西 杀死一个活动,虽然我想这不能保证)并且只是从头开始重新创建活动? 这是一个简单的小应用程序,因此重新创建活动的开销 没什么大不了的。只是好奇什么是“正确的”。

我想这只是计划不周和缺乏知识的结果(我只是为了好玩而不是为了工作而编程)所以如果我不得不走艰难的路线,我想这是一种学习经历,对吧?

【问题讨论】:

  • 我很困惑。您展示的示例代码是 Firebase 存储的进度侦听器。但是您的文字显然是关于数据库的。您遇到了哪一个问题?
  • 对弗兰克的困惑感到抱歉。我本来可以更清楚的。我正在使用 Firebase 的两个 API(数据库和存储),并且两者都有监听器。我想我的问题确实适用于两者。我猜一般来说 Firebase 监听器以及当他们需要和不需要分离/删除时。例如,是否有一些 FB 侦听器会在 Activity 移出视图时自行处理,或者即使在 onPause/Stop/Destroy 等之后,每个侦听器(DB 和存储)也会继续侦听。

标签: android memory-leaks firebase firebase-storage


【解决方案1】:

在 Activity 停止时自动取消注册侦听器是 android 中“Task”类及其派生类 (StorageTask) 的一项功能。

这意味着你可以这样做:

UploadTask uploadTask = ref.putFile(uploadFile);

uploadTask.addOnFailureListener(thisActivity, new OnFailureListener() {
//@Override code here
}).addOnSuccessListener(thisActivity, new OnSuccessListener<UploadTask.TaskSnapshot>() {
//@Override code here
}).addOnProgressListner(thisActivity, new OnProgressListner<UploadTask.TaskSnapshot>() {
//@Override code here
};

您也可以使用从实时数据库返回的任务对象来执行此操作,例如 setValue,如下所示:

databaseReference.setValue("newValue").addOnSuccessListener(thisActivity, ...)

所以直接回答你的问题:

  1. 使用活动范围的版本在活动停止时自动取消注册侦听器。请注意,对于存储,您可以在 Activity 开始时使用 StorageReference.getActiveUploadTasks 和 StorageReference.getActiveDownloadTasks 查询正在运行的操作并重新订阅。

  2. 如果使用范围侦听器,则无需手动取消订阅。我不知道批量取消订阅非基于任务的侦听器的方法。

  3. 好吧,我不确定您如何保证操作系统将始终终止您的任务,而不是再次停止/启动它——以及如何保证您的完成代码运行。我建议您将代码移至 onStart

【讨论】:

  • 太棒了!谢谢你。出色的答案,正是我正在寻找的信息。那么你在存储示例中放置“thisActivity”的位置是否与我放置“this”或“this”描述的不是活动相同?我看到我可以做“this.getCallingActivity”和其他一些事情。您能告诉我引用该活动的正确方法是什么,这样我就不会最终引用其他内容吗?另外,我会听取您的建议并将我的一些 onCreate() 逻辑移至 onStart()。一开始就应该在那里。以艰难的方式吸取教训! ;)
  • 通常“this”指的是在活动代码内部的活动。但是,如果您在嵌套类或回调例程中,则可能不会。如果您发现自己在那里,您可以通过使用类型限定“this”来专门引用该活动——如“MainActivity.this”
  • 最后的评论只是锦上添花。内存泄漏解决了:)
  • @BenjaminWulfe 我似乎无法对addValueEventListener 做同样的事情。有什么想法吗?
  • 有没有办法在片段中注销监听器?
猜你喜欢
  • 1970-01-01
  • 2013-02-15
  • 1970-01-01
  • 2017-10-03
  • 1970-01-01
  • 1970-01-01
  • 2016-06-22
  • 1970-01-01
  • 2012-08-25
相关资源
最近更新 更多