Uygulamanızın belleğini yönetme

Bu sayfada, uygulamanızın bellek kullanımını proaktif olarak nasıl azaltabileceğiniz açıklanmaktadır. Daha fazla bilgi için belleği nasıl yönettiğini öğrenmek için bkz. Bellek yönetimine genel bakış.

Rastgele erişimli bellek (RAM), yazılım geliştirme ortamları için değerli bir kaynaktır. Fiziksel belleğin genellikle kısıtlı olduğu bir mobil işletim sistemi için daha da değerlidir. Hem Android Runtime (ART) hem de Dalvik sanal makinesi, rutin çöpler gerçekleştirse de bu, uygulamanızın belleği ne zaman ve nerede ayırıp serbest bıraktığını göz ardı edebileceğiniz anlamına gelmez. Yine de, genellikle nesnede tutunmasından kaynaklanan bellek sızıntıları oluşturmaktan kaçınmanız gerekir. referansları varsa ve mevcut tüm öğeleri Reference nesne doğru zamanı ifade eder.

Kullanılabilir bellek ve bellek kullanımını izleme

Düzeltebilmeniz için önce uygulamanızın bellek kullanımı sorunlarını bulmanız gerekir. İlgili içeriği oluşturmak için kullanılan Android Studio'daki Bellek Profil Aracı, ve hafıza sorunlarını aşağıdaki şekillerde teşhis edebilirsiniz:

  • Uygulamanızın zaman içinde belleği nasıl ayırdığını görün. Memory Profiler'da, öğelerin gerçek zamanlı olarak uygulamanızın kullandığı bellek miktarı, ayrılan Java nesnelerinin sayısı ve atık toplama zamanı gerçekleşir.
  • Uygulamanız çalışırken çöp toplama etkinlikleri başlatın ve Java yığınının anlık görüntüsünü alın koşar.
  • Uygulamanızın bellek tahsislerini kaydedin, ayrılan tüm nesneleri inceleyin, ayırabilir ve Android Studio düzenleyicisinde ilgili koda atlayabilirsiniz.

Etkinliklere göre bellek serbest bırakma

Android, bellekte yer açmak için gerekirse uygulamanızdaki belleği geri alabilir veya uygulamanızı tamamen durdurabilir. kritik görevler için, Bellek yönetimine genel bakış. Daha fazla yardım almak için sistem belleğini dengelemek ve sistemin, uygulama işleminizi durdurma ihtiyacını ortadan kaldırmak için, "the" ComponentCallbacks2. Activity sınıfınızda kullanabilirsiniz. Sağlanan onTrimMemory(). geri çağırma yöntemi, uygulamanız arka plana alabilirsiniz. Ardından uygulamanızın, uygulama yaşam döngüsüne göre nesneleri yayınlamasını sağlar. sistemin belleği geri alması gerektiğini gösteren sistem etkinlikleridir.

Bellekle ilgili farklı değişikliklere yanıt vermek için onTrimMemory() geri çağırmasını uygulayabilirsiniz. etkinlikleri için aşağıdaki örnekte gösterildiği gibi:

Kotlin

import android.content.ComponentCallbacks2
// Other import statements.

class MainActivity : AppCompatActivity(), ComponentCallbacks2 {

    // Other activity code.

    /**
     * Release memory when the UI becomes hidden or when system resources become low.
     * @param level the memory-related event that is raised.
     */
    override fun onTrimMemory(level: Int) {

        // Determine which lifecycle or system event is raised.
        when (level) {

            ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN -> {
                /*
                   Release any UI objects that currently hold memory.

                   The user interface moves to the background.
                */
            }

            ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE,
            ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW,
            ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL -> {
                /*
                   Release any memory your app doesn't need to run.

                   The device is running low on memory while the app is running.
                   The event raised indicates the severity of the memory-related event.
                   If the event is TRIM_MEMORY_RUNNING_CRITICAL, then the system
                   begins stopping background processes.
                */
            }

            ComponentCallbacks2.TRIM_MEMORY_BACKGROUND,
            ComponentCallbacks2.TRIM_MEMORY_MODERATE,
            ComponentCallbacks2.TRIM_MEMORY_COMPLETE -> {
                /*
                   Release as much memory as the process can.

                   The app is on the LRU list and the system is running low on memory.
                   The event raised indicates where the app sits within the LRU list.
                   If the event is TRIM_MEMORY_COMPLETE, the process is one of the
                   first to be terminated.
                */
            }

            else -> {
                /*
                  Release any non-critical data structures.

                  The app receives an unrecognized memory level value
                  from the system. Treat this as a generic low-memory message.
                */
            }
        }
    }
}

Java

import android.content.ComponentCallbacks2;
// Other import statements.

public class MainActivity extends AppCompatActivity
    implements ComponentCallbacks2 {

    // Other activity code.

    /**
     * Release memory when the UI becomes hidden or when system resources become low.
     * @param level the memory-related event that is raised.
     */
    public void onTrimMemory(int level) {

        // Determine which lifecycle or system event is raised.
        switch (level) {

            case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:

                /*
                   Release any UI objects that currently hold memory.

                   The user interface moves to the background.
                */

                break;

            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:

                /*
                   Release any memory your app doesn't need to run.

                   The device is running low on memory while the app is running.
                   The event raised indicates the severity of the memory-related event.
                   If the event is TRIM_MEMORY_RUNNING_CRITICAL, then the system
                   begins stopping background processes.
                */

                break;

            case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
            case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
            case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:

                /*
                   Release as much memory as the process can.

                   The app is on the LRU list and the system is running low on memory.
                   The event raised indicates where the app sits within the LRU list.
                   If the event is TRIM_MEMORY_COMPLETE, the process is one of the
                   first to be terminated.
                */

                break;

            default:
                /*
                  Release any non-critical data structures.

                  The app receives an unrecognized memory level value
                  from the system. Treat this as a generic low-memory message.
                */
                break;
        }
    }
}

Ne kadar belleğe ihtiyacınız olduğunu kontrol etme

Android, çalışan birden fazla işleme izin vermek için her işleme ayrılan yığın boyutuyla ilgili kesin bir sınır belirler. uygulamasını indirin. Tam yığın boyutu sınırı, cihazın ne kadar RAM'e sahip olduğuna bağlı olarak cihazlar arasında değişir. yardımcı olabilir. Uygulamanız yığın kapasitesine ulaşır ve daha fazla bellek tahsis etmeye çalışırsa sistem OutOfMemoryError.

Bellek yetersizliğini önlemek amacıyla, sisteme sorgu göndererek ne kadar yığın alanının geçerli cihazda kullanılabilir. Şu numarayı arayarak sisteme bu rakam için sorgu gönderebilirsiniz: getMemoryInfo() Bu, ActivityManager.MemoryInfo. cihazın geçerli bellek durumuyla ilgili bilgi sağlayan nesne bellek düzeyi, toplam bellek ve bellek eşiği (sistemin veriler çok önemli bir parçasıdır. ActivityManager.MemoryInfo nesnesi, lowMemory, Bu, cihazın belleğinin azalıp kalmadığını gösteren basit bir boole değeridir.

Aşağıdaki örnek kod snippet'i, getMemoryInfo() yönteminin en iyi şekilde yararlanabilirsiniz.

Kotlin

fun doSomethingMemoryIntensive() {

    // Before doing something that requires a lot of memory,
    // check whether the device is in a low memory state.
    if (!getAvailableMemory().lowMemory) {
        // Do memory intensive work.
    }
}

// Get a MemoryInfo object for the device's current memory status.
private fun getAvailableMemory(): ActivityManager.MemoryInfo {
    val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    return ActivityManager.MemoryInfo().also { memoryInfo ->
        activityManager.getMemoryInfo(memoryInfo)
    }
}

Java

public void doSomethingMemoryIntensive() {

    // Before doing something that requires a lot of memory,
    // check whether the device is in a low memory state.
    ActivityManager.MemoryInfo memoryInfo = getAvailableMemory();

    if (!memoryInfo.lowMemory) {
        // Do memory intensive work.
    }
}

// Get a MemoryInfo object for the device's current memory status.
private ActivityManager.MemoryInfo getAvailableMemory() {
    ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
    ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
    activityManager.getMemoryInfo(memoryInfo);
    return memoryInfo;
}

Bellek açısından daha verimli kod yapıları kullanın

Bazı Android özellikleri, Java sınıfları ve kod yapıları, diğerlerinden daha fazla bellek kullanır. Şunları yapabilirsiniz: kodunuzda daha verimli alternatifler seçerek uygulamanızın kullandığı bellek miktarını en aza indirin.

Hizmetleri ölçülü kullanın

Gereksiz durumlarda hizmetleri çalışır durumda bırakmamanızı önemle tavsiye ederiz. Gereksiz bırakılıyor bir Android uygulamasının yapabileceği en kötü bellek yönetimi hatalarından biri. Uygulamanız arka planda çalışması için bir hizmete ihtiyaç duyuyorsa bir iş çıkarması gerekmediği sürece çalışır. Görevini tamamladığında hizmetinizi durdurun. Aksi halde bellek sızıntısına neden olabilirsiniz.

Bir hizmeti başlattığınızda, sistem o hizmet için işlemin devam etmesini tercih eder. Bu davranışı nedeniyle hizmet işlemleri çok pahalıya mal olur, çünkü hizmet tarafından kullanılan RAM diğer işlemler için kullanılamaz. Bu da sistemin otomatik olarak kaydedebileceği önbellek işlemlerinin sayısını azaltır LRU önbelleğinde tutulur. Bu da uygulama geçişinin daha verimsiz olacağı anlamına gelir. Hatta ekip arkadaşlarınızın kafa karışıklıklarını gidermek için sistem, tüm hizmetleri barındırmaya yetecek kadar işlem gerçekleştiremediğinde şu anda çalışıyor.

Genellikle, kullanılabilir hizmetlere ilişkin sürekli talepler nedeniyle kalıcı hizmetlerden kaçının hafızada bulabilirsiniz. Bunun yerine, WorkManager Okuyucu Gelirleri Yöneticisi'ni arka plan işlemlerini programlamak için WorkManager yönteminin nasıl kullanılacağı hakkında bilgi için bkz. Sürekli çalışma.

Optimize edilmiş veri kapsayıcılarını kullanın

Programlama dili tarafından sağlanan sınıflardan bazıları mobil cihazlarda kullanım için optimize edilmemiş cihazlar. Örneğin, HashMap uygulaması bellek olabilir verimsizdir. Çünkü her eşleme için ayrı bir giriş nesnesine ihtiyaç duyar.

Android çerçevesi, aşağıdakiler de dahil olmak üzere optimize edilmiş çeşitli veri kapsayıcısı içerir: SparseArray, SparseBooleanArray, ve LongSparseArray. Örneğin SparseArray sınıfları, sistemin gerek otomatik kutu anahtarı ve bazen değeri de içerir. Bu da giriş başına bir veya iki nesne daha oluşturur.

Gerekirse yalın veri yapısı için her zaman ham dizilere geçebilirsiniz.

Kod soyutlamalarında dikkatli olun

Geliştiriciler, kodları geliştirebildiği için soyutlamaları genellikle iyi bir programlama uygulaması olarak kullanırlar. esnek olma ve bakım. Ancak soyutlamaların maliyeti çok daha yüksektir. genellikle yürütülmesi gereken daha fazla kod gerektirir. Bu da, eşleme için daha fazla zaman ve RAM bir kod snippet'i ekleyin. Soyutlamalarınız önemli ölçüde faydalı değilse bunlardan kaçının.

Serileştirilmiş veriler için basit protobuf'ları kullan

Protokol tamponlar (protobuf'lar), Google Analytics 4'te Google tarafından tasarlanan Yapılandırılmış verileri serileştirmek için Google'ı kullanır. XML'e benzer ancak daha küçük, daha hızlı ve daha basittir. Eğer verileriniz için protobuf kullanıyorsanız, istemci taraflı kodunuzda her zaman basit protokol kullanın. 87 Oktan protobuf'lar son derece ayrıntılı kod oluşturur. Bu da uygulamanızda RAM kullanımında artış, APK boyutunda önemli artış ve daha yavaş yürütme.

Daha fazla bilgi için protobuf benioku.

Bellek karmaşasını önleyin

Çöp toplama etkinlikleri uygulamanızın performansını etkilemez. Ancak birçok çöp toplama işlemi kısa bir süre içinde meydana gelen olaylar da pilin hızlı bir şekilde tükenmesine neden olabileceği gibi, marjinal şekilde de çöp toplayıcı ile arasındaki gerekli etkileşimler nedeniyle kare oluşturma süresini uzatır uygulama iş parçacıklarıdır. Sistem atık toplama işlemine ne kadar fazla zaman harcarsa pil o kadar hızlı gider.

Bellek karması genellikle çok sayıda atık toplama etkinliğinin oluşmasına neden olabilir. İçinde alıştırma olarak bilinen bellek karmaşası, belirli bir teşekkür ederiz.

Örneğin, bir for döngüsü içinde birden fazla geçici nesne ayırabilirsiniz. Alternatif olarak, yeni bir Paint veya İçinde Bitmap nesne var onDraw() fonksiyonudur. Her iki durumda da uygulama, çok sayıda nesneyi yüksek ses seviyesinde hızlı bir şekilde oluşturur. Bu Üretken yapay zeka, genç nesilde mevcut tüm belleği hızla tüketerek atık toplama işlemini zorunlu kılar. gerçekleşeceği tahmin edilen iyileşmeleri görebilirsiniz.

Şuradaki yerleri bulmak için Bellek Profil Aracı'nı kullanın: bu sorunları düzeltmeden önce bellek karmaşasının yüksek olduğu bir kod görüntülersiniz.

Kodunuzdaki sorunlu alanları belirledikten sonra, bu alandaki ayırma sayısını azaltmaya çalışın kritik önemdeki alanlar var. Her şeyi iç döngülerden alabilir veya fabrika tabanlı çok önemlidir.

Nesne havuzlarının kullanım alanına fayda sağlayıp sağlamadığını da değerlendirebilirsiniz. Nesne havuzuyla, zemine bir nesne örneği bırakırsanız, artık ihtiyaç duyulmadığında bunu bir havuzda serbest bırakırsınız. Bu tür bir nesne örneği tekrar gerektiğinde bu örnek yerine havuzdan en iyi uygulamaları paylaşacağım.

Bir nesne havuzunun belirli bir durumda uygun olup olmadığını belirlemek için performansı derinlemesine değerlendirin. Nesne havuzlarının performansı düşürebileceği durumlar vardır. Havuzlarda başka genel giderlere yol açar. Örneğin, havuz bakımı genellikle senkronizasyonuna yardımcı olur. Ayrıca, havuza alınan nesne örneğini sürüm sırasında bellek sızıntılarını önler ve edinme sırasında başlatmanın sıfır olmayan bir değeri olabilir yardımcı olabilir.

Havuzda gerekenden daha fazla nesne örneğinin saklanması da çöpe yük oluşturur koleksiyonudur. Nesne havuzları atık toplama çağrılarının sayısını azaltsa da her çağrı için gereken iş miktarını artırarak etkin (erişilebilir) baytlar olabilir.

Yoğun bellek kullanan kaynakları ve kitaplıkları kaldırma

Kodunuzdaki bazı kaynaklar ve kitaplıklar, fark etmeden belleği tüketebilir. İlgili içeriği oluşturmak için kullanılan üçüncü taraf kitaplıklar veya yerleştirilmiş kaynaklar dahil olmak üzere uygulamanızın genel boyutu, tükettiğini göreceksiniz. Gereksiz etiketleri kaldırarak uygulamanızın bellek tüketimini artırabilirsiniz. ya da olması gerekenden daha fazla yer kaplayan bileşenler veya kaynaklar ile kitaplıklar.

Genel APK boyutunu küçültün

Uygulamanızın genel boyutunu küçülterek uygulamanızın bellek kullanımını önemli ölçüde azaltabilirsiniz. Bit eşlem boyutu, kaynaklar, animasyon çerçeveleri ve üçüncü taraf kitaplıkların tümü en iyi yoludur. Android Studio ve Android SDK, uygulamanızın boyutunu küçültmeye yardımcı olacak kaynaklar ve dış bağımlılıklar hakkında bilgi edindiniz. Bu araçlar, RACI matrisleri gibi modern kod küçültme yöntemlerini destekler: R8 derlemesi.

Uygulamanızın genel boyutunu küçültme hakkında daha fazla bilgi için bkz. Uygulamanızın boyutunu küçültün.

Bağımlılık yerleştirme için Hilt veya Dagger 2'yi kullanma

Bağımlılık yerleştirme çerçeveleri, yazdığınız kodu basitleştirebilir ve uyarlanabilir bir test ve diğer yapılandırma değişiklikleri için yararlı bir ortamdır.

Uygulamanızda bağımlılık yerleştirme çerçevesi kullanmayı planlıyorsanız Hilt veya Dagger. Hilt, bir bağımlılık yerleştirmedir geliştirmeyi öğreneceksiniz. Dagger, uygulamanızın özelliklerini taramak için yansıma girin. Dagger'ın statik derleme süresi uygulamasını, Android uygulamalarında veya bellek kullanımından sorumludur.

Yansıma başlatma işlemlerini kullanan diğer bağımlılık ekleme çerçeveleri, kodunu da ekleyin. Bu işlem çok daha fazla CPU döngüsü ve RAM gerektirebilir ve Uygulama kullanıma sunulduğunda kayda değer bir gecikme.

Harici kitaplıkların kullanımına dikkat edin

Harici kitaplık kodu, genellikle mobil ortamlar için yazılmaz ve bir mobil istemci üzerinde çalışıyor. Harici bir kitaplık kullandığınızda bu kitaplığı optimize etmeniz gerekebilir mobil cihaz kitaplığı. Bu çalışmayı önceden planlayın ve kitaplığı şu unsurlar açısından analiz edin: ve RAM ayak izini gösterir.

Mobil cihazlar için optimize edilmiş bazı kitaplıklar bile farklı uygulamalar nedeniyle sorunlara neden olabilir. Örneğin, Örneğin, bir kitaplık basit protobuf'lar kullanırken başka bir kütüphanede mikro protobuflar kullanılabilir ve bu da iki nasıl kullanabileceğinizi göstereceğiz. Bu durum, farklı türlerde ya da günlük kaydı, analizler, görüntü yükleme çerçeveleri, önbelleğe alma ve beklemediğiniz daha pek çok şey.

ProGuard, API'lerin ve kaynakların kaldırılmasına yardımcı olsa da bir kitaplığın büyük iç bağımlılıklarını kaldıramaz. İstediğiniz özellikler bu kitaplıklar daha düşük düzeyde bağımlılıklar gerektirebilir. Bu durum özellikle de Activity alt sınıfını çok sayıda bağımlılığın söz konusu olduğu bir kitaplık. Yaygın bir uygulamadır ve çalışması için ProGuard'ın manuel olarak ayarlanmasını gerektirir.

Onlarca özellik arasından yalnızca bir veya iki özellik için paylaşılan kitaplık kullanmaktan kaçının. Geniş bir ve ek yükten kurtarır. Bir kitaplığı kullanıp kullanmayacağınıza karar verirken bir uygulamaya ne dersiniz? Aksi takdirde, dilerseniz bazı ipuçları vereceğim.