我真的应该删除 ValueEventListener 吗?
Posted
技术标签:
【中文标题】我真的应该删除 ValueEventListener 吗?【英文标题】:Should I actually remove the ValueEventListener? 【发布时间】:2018-07-29 09:41:33 【问题描述】: DatabaseReference Ref = FirebaseDatabase.getInstance().getReference(Constants.Client + "/" + path);
Ref.keepSynced(true);
Ref.addValueEventListener(new ValueEventListener()
@Override
public void onDataChange(DataSnapshot dataSnapshot)
@Override
public void onCancelled(DatabaseError databaseError)
);
我知道ValueEventListener
在一个新线程中运行,我是否应该在任何时候删除它以进行正确的线程管理? (例如并行运行的线程不多)。如果是,怎么做?
【问题讨论】:
是的。您应该在组件生命周期中将其删除。否则它将在不知道组件状态的情况下为您提供回调(称为 Activity)。移除onStop()
或onDestroy()
中的监听器。
我已经尝试删除它,我已经尝试了所有堆栈溢出的答案,但我无法删除它。有人可以帮忙吗?
【参考方案1】:
在谈论监听器时,是的,您需要根据活动的生命周期删除它们,为此您需要使用以下代码行:
databaseReference.removeEventListener(valueEventListener);
请记住,如果您不这样做,您最终会浪费电池和带宽。所以:
-
如果您在
onStart
中添加了侦听器,则必须在onStop
中删除它。
如果您在onResume
中添加了侦听器,则必须在onPause
中删除它。
如果您在onCreate
中添加了侦听器,则必须在onDestroy
中删除它。
但请记住,onDestroy
总是被 not
调用,所以最后一个选项并不总是一个好的选择。
还有另一种不需要删除监听器的方法,那就是使用addListenerForSingleValueEvent:
为此位置的数据中的单个更改添加侦听器。
【讨论】:
为什么不总是调用 onDestroy? 请查看here和here,以便更好地理解。 使用 addListenerForSingleValueEvent() 时,您仍应将其从 DatabaseReference 中删除。如果它永远不会触发(设备离线),则永远不会自动删除侦听器,并可能导致内存泄漏。 @javmarina 使用addListenerForSingleValueEvent()
时,没有应删除的侦听器,因为侦听器只触发一次。
我检查了addListenerForSingleValueEvent()
的源代码,它基本上添加了一个新的侦听器,当onDataChange()
被调用时它会被删除。如果两个回调方法都没有被触发,例如当设备离线时,监听器不会被移除。尽管这种情况很少见,但我们应该在代码中处理它。请参阅我对我提出的解决方案的回答。【参考方案2】:
要删除 ValueEventListener,您可以这样做:
移除监听者的匿名性。
从这里更改代码:-
Ref.addValueEventListener(new ValueEventListener()
@Override
public void onDataChange(DataSnapshot dataSnapshot)
@Override
public void onCancelled(DatabaseError databaseError)
);
进入这个:
ValueEventListener listener= new ValueEventListener()
@Override
public void onDataChange(DataSnapshot dataSnapshot)
@Override
public void onCancelled(DatabaseError databaseError)
);
Ref.addValueEventListener(listener);
现在您可以移除监听器了:
@Override
public void onDestroy()
if (Ref != null && listener != null)
Ref.removeEventListener(listener);
您需要删除它,这样监听器就不会在其他活动生命周期中保持运行,例如 onDestroy()
【讨论】:
【参考方案3】:我遇到了同样的问题,导致大量内存泄漏。所以我创建了一个新类来处理添加的侦听器,并在调用相应的方法(onPause()、onStop() 或 onDestroy())时将其删除。使用androidx.lifecycle 库,适用于活动和片段(实际上,任何实现LifecycleOwner 的类)。
您可以查看代码here。如果不手动添加 androidx.lifecycle 依赖项,您可能会很好,但您也可以将其添加到模块级 build.gradle:
implementation 'androidx.lifecycle:lifecycle-runtime:VERSION'
在您当前的代码中,而不是:
databaseReference.addValueEventListener(valueEventListener);
// or
databaseReference.addListenerForSingleValueEvent(valueEventListener);
你需要使用:
addValueEventListener(databaseReference, valueEventListener);
// or
addListenerForSingleValueEvent(databaseReference, valueEventListener);
这在从使用 FirebaseListenerHandler 的活动或片段中调用时有效,如 gist 所示。如果您需要在其他情况下(如服务)添加 Firebase 侦听器,您仍然需要手动删除它们。
【讨论】:
以上是关于我真的应该删除 ValueEventListener 吗?的主要内容,如果未能解决你的问题,请参考以下文章