Merhabalar.
Bu yazımda Android’de bazen başımıza büyük işler çıkaran bellek sızıntıları ve onlarla nasıl başa çıkılabileceğinden bahsedeceğim.
Bellek sızıntısı nedir?
Uygulama çalışmaya devam ederken Application Not Responding(ANR) hatası alıp uygulama kapanıyorsa ya da bazı durumlarda gecikmeler yaşanıyorsa bunun sebebi bellek sızıntısıdır. Ayrıca uygulamayı kodlarken loglarda OutOfMemoryError
hatası görmüş olabilirsiniz. İşte bunun sebebi de bellek sızıntısıdır.
Bildiğiniz üzere Garbage Collector gerekli olmayan nesnelerin referansını siler. Eğer uygulamanızda kullanmadığınız nesneleri tutuyorsanız gereksiz yere referans tutarsınız ve bellek şişmeye başlar dolayısıyla bellek sızıntısı olur. En basitinden bile bir uygulama yapıyorsanız bellek sızıntısı problemi ile karşı karşıya kalabilirisiniz. Ama onu alt etmek tahmin edildiği kadar zor değildir.
- Arka planda ui, belirli nesnenin referansını tutar. Bellek sızıntısına yol açtığı için, arka plan görevindeki ui nesnesinin referansını asla tutmayın.
- Static viewler kullanmaktan kaçının. Çünkü static viewlerin referansı silinmez.
- Asla static
Context
kullanmayın.
1 2 3 4 |
public class MainActivity extends AppCompatActivity { private static TextView textView; // STATIC VIEW KULLANMAYIN private static Context context; // STATIC CONTEXT KULLANMAYIN } |
Context
kullanırken dikkatli olun, hangi contextin uygun yerlerde olduğuna karar vermek en önemlisidir. Mümkünse application context kullanın.- Bir listener başlatmışsanız onu mutlaka
onStop
,onPause
ya daonDestroy
metodları içinde null ya da unregister yapın.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class LocationListenerActivity extends Activity implements LocationUpdate { @Override public void onLocationChange(Location location){ } @Override public void onStart(){ LocationListener.get().register(this); } @Override public void onStop(){ LocationListener.get().unregister(this); } } |
- Inner classlar kullanın. Eğer inner class kullanacaksanız bunu static yapın çünkü static sınıf içerisinde bulunduğu sınıfa referans vermez. Inner class içerisinde de viewler kullanacaksanız bunları constructor aktarın ve weak reference (zayıf referans) olmasını sağlayın.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
public class MainActivity extends AppCompatActivity { TextView textView; AsyncTask asyncTask; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.textView); asyncTask = new MyBackgroundTask(textView).execute(); } @Override protected void onDestroy() { asyncTask.cancel(true); super.onDestroy(); } private static class MyBackgroundTask extends AsyncTask<Void, Void, String> { private final WeakReference<TextView> textViewReference; public MyBackgroundTask(TextView textView) { this.textViewReference = new WeakReference<>(textView); } @Override protected void onCancelled() { } @Override protected String doInBackground(Void... params) { return "some text"; } @Override protected void onPostExecute(String result) { TextView textView = textViewReference.get(); if (textView != null) { textView.setText(result); } } } } |
- Anonim sınıfların kullanımına dikkat edin. Çünkü anonim sınıf kullanmak static olmayan inner class kullanmaya benzer.
WeakHashMap
gibi collection yapılarında kesinlike view tutmayın. Çünkü bu yapı viewleri hard reference olarak tutar.
İşte tüm bunlar bellek sızıntısına sebep olan ve kullanıcıların uygulamayı kaldırmasına sebebiyet veren nedenler.
Peki tüm bunlar kontrolümüz dışından gerçekleşiyorsa, yukarıda saydığım nedenlerin dışında bir nedenden dolayı sızıntı gerçekleşiyorsa ve bu sızıntıları tespit etmekte zorlanıyorsak ne yapacağız?
Tam da bu vakit karşımıza hayat kurtacı bir kütüphane olan LeakCanary çıkıyor. Bu kütüphane size bellek sızıntısının nerede olduğunu ve hangi nedenden kaynaklandığını haber veriyor. Tek yapmanız gereken kendi dökümanında yer alan birkaç satır kodu projenize eklemek. Sonrasında LeakCanary uygulamanızın yanına bir uygulama gibi kuruluyor. Yani siz debug yaptığınızda 2 uygulama telefona/emulatore kuruluyor ve LeakCanary uygulamasını açtığınızda -varsa- bellek sızıntıları size gösteriliyor.
Umarım faydalı olmuştur.
Hepinize bol kodlu günler.