2016-08-10 3 views
0

Я получаю много утечек памяти в приложении, которое я создал. Я создал очень простое приложение, чтобы воспроизвести проблему. Это приложение просто ссылается на FirebaseDatabase и настраивает ChildEventListener. Когда пользователь нажимает кнопку, он добавляет запись в базу данных и запускает новое действие, которое делает System.gc().Это мой код или код Firebase, вызывающий эту утечку?

Нажатие кнопки несколько раз приведет к утечке канарейки для создания дампа.

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?

EDIT: @ Ответ 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) { 

     } 
    }; 
} 

}

ответ

1

Я не использовал LeakCanary, так что это всего лишь догадка.

ChildEventListeners должно быть unregistered, когда они больше не нужны. Часто слушатели добавляются и удаляются в методах жизненного цикла активности, таких как onCreate() и onDestroy(). Вместо создания анонимного прослушивателя создайте объект такого типа и удалите его с помощью Query.removeEventListener(), когда больше не нужно видеть, устраняет ли это отчет об утечке.

0

Я думаю, что лучше добавлять/удалять слушателей в onStart()/onStop() или обратные вызовы onCreate()/onDestroy() соответственно.

Если слушатель был добавлен в onCreate() и удален в onStop(), может возникнуть ситуация, когда действие будет восстановлено без вызова onCreate(), но с вызовом onStart(), и слушатель не будет установлен ,

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

 Смежные вопросы

  • Нет связанных вопросов^_^