【问题标题】:Should I actually remove the ValueEventListener?我真的应该删除 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()中的监听器。
  • 我已经尝试删除它,我已经尝试了所有堆栈溢出的答案,但我无法删除它。有人可以帮忙吗?

标签: java android multithreading firebase firebase-realtime-database


【解决方案1】:

在谈论监听器时,是的,您需要根据活动的生命周期删除它们,为此您需要使用以下代码行:

databaseReference.removeEventListener(valueEventListener);

请记住,如果您不这样做,您最终会浪费电池和带宽。所以:

  1. 如果您在onStart 中添加了侦听器,则必须在onStop 中删除它。
  2. 如果您在onResume 中添加了侦听器,则必须在onPause 中删除它。
  3. 如果您在onCreate 中添加了侦听器,则必须在onDestroy 中删除它。

但请记住,onDestroy 总是被 not 调用,所以最后一个选项并不总是一个好的选择。

还有另一种不需要删除监听器的方法,那就是使用addListenerForSingleValueEvent

为此位置的数据中的单个更改添加侦听器。

【讨论】:

  • 为什么不总是调用 onDestroy?
  • 请查看herehere,以便更好地理解。
  • 使用 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 侦听器,您仍然需要手动删除它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-23
      相关资源
      最近更新 更多