【问题标题】:Is this my code or Firebase code causing this leak?这是我的代码还是导致此泄漏的 Firebase 代码?
【发布时间】:2016-08-10 19:58:46
【问题描述】:

在我创建的应用程序中出现大量内存泄漏。我创建了一个非常简单的应用程序来重现该问题。此应用程序仅引用 FirebaseDatabase 并设置 ChildEventListener。当用户单击按钮时,它会向数据库添加一条记录,并启动一个执行 System.gc() 的新活动。

多次按下按钮将导致 Leak Canary 生成转储。

MainActivity.java:

public class MainActivity extends AppCompatActivity {

private FirebaseDatabase firebaseDatabase;
private DatabaseReference dbRef;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    firebaseDatabase = FirebaseDatabase.getInstance();
    dbRef = firebaseDatabase.getReference("leak");
    dbRef.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
        }
    });

    findViewById(R.id.btn_leak).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            dbRef.child(UUID.randomUUID().toString()).setValue("Yes");
            Intent leakIntent = new Intent(getApplicationContext(), LeakActivity.class);
            startActivity(leakIntent);
        }
    });

}

}

LeakActivity.java:

public class LeakActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.leak);

        System.gc();
    }
}

由于帖子限制,泄漏的金丝雀日志为here.

我在代码中做错了什么,还是这与 Firebase 有关?

编辑: @qbix 的回答似乎有效。对于其他人,这是 MainActivity.java 的工作版本:

public class MainActivity extends AppCompatActivity {

private FirebaseDatabase firebaseDatabase;
private DatabaseReference dbRef;
private ChildEventListener dbListener;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    firebaseDatabase = FirebaseDatabase.getInstance();
    dbRef = firebaseDatabase.getReference("leak");
    dbListener = getDbListener();
    dbRef.addChildEventListener(dbListener);

    findViewById(R.id.btn_leak).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            dbRef.child(UUID.randomUUID().toString()).setValue("Yes");
            Intent leakIntent = new Intent(getApplicationContext(), LeakActivity.class);
            startActivity(leakIntent);
        }
    });
}

@Override
protected void onStop() {
    dbRef.removeEventListener(dbListener);
    super.onStop();
}

private ChildEventListener getDbListener(){
    return new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    };
}

}

【问题讨论】:

    标签: java android memory-leaks firebase leakcanary


    【解决方案1】:

    我没有使用过 LeakCanary,所以这只是一个有根据的猜测。

    ChildEventListeners 在不再需要时需要为 unregistered。通常在活动生命周期方法中添加和删除侦听器,例如onCreate()onDestroy()。与其创建匿名侦听器,不如创建该类型的对象并在不再需要时使用 Query.removeEventListener() 将其删除,以查看是否消除了泄漏报告。

    【讨论】:

      【解决方案2】:

      我认为最好分别在 onStart()/onStop() 或 onCreate()/onDestroy() 回调中添加/删除侦听器。

      如果在 onCreate() 中添加了侦听器并在 onStop() 中删除了侦听器,则可能会出现以下情况:无需调用 onCreate() 但调用 onStart() 即可恢复活动,并且不会设置侦听器。

      https://developer.android.com/images/activity_lifecycle.png

      【讨论】:

        猜你喜欢
        • 2017-12-05
        • 2020-01-29
        • 1970-01-01
        • 1970-01-01
        • 2013-04-04
        • 2012-01-18
        • 1970-01-01
        • 2023-03-11
        • 1970-01-01
        相关资源
        最近更新 更多