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 ayırmalarını kaydedin, ayrılan tüm nesneleri inceleyin, her ayırma için yığın izlemeyi görüntüleyin ve Android Studio düzenleyicisinde ilgili koda atlayın.

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ı yaşam döngüsü veya bellekle ilgili, iyi bir performans gösteren gönüllü olarak bellek kullanımını azaltması için bir fırsattır. Bellekte yer açmak, çok dikkatli olmanız gerekir. düşük bellek kapasitesine sahip.

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) {

        if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
            // Release memory related to UI elements, such as bitmap caches.
        }

        if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
            // Release memory related to background processing, such as by
            // closing a database connection.
        }
    }
}

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) {

        if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
            // Release memory related to UI elements, such as bitmap caches.
        }

        if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
            // Release memory related to background processing, such as by
            // closing a database connection.
        }
    }
}

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;
}

Daha fazla bellek tasarrufu sağlayan 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 hizmetleri çalışır durumda bırakmak, bir Android uygulamasının yapabileceği en kötü bellek yönetimi hatalarından biridir. 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 yer alır. 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, SparseArray, SparseBooleanArray ve LongSparseArray gibi çeşitli optimize edilmiş veri kapsayıcıları içerir. Ö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, sade bir veri yapısı için dilediğiniz zaman ham dizilere geçebilirsiniz.

Kod soyutlamalarıyla ilgili 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. Verileriniz için protobuf kullanıyorsanız istemci tarafı kodunuzda her zaman hafif protobuf'leri 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, performans açısından kritik alanlarda ayırma sayısını azaltmaya çalışın. 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, serbest bırakma sırasında bellek sızıntılarını önlemek için havuzlanmış nesne örneğini temizlemek ve ardından edinme sırasında bu örneğin başlatılması sıfır olmayan bir yükü beraberinde getirebilir.

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.

Bellek yoğun 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 ekleme çerçevesi kullanmayı düşünüyorsanız Hilt veya Dagger'ı kullanmayı düşünebilirsiniz. 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 zamanı uygulamasını, gereksiz çalışma zamanı maliyeti veya bellek kullanımı olmadan Android uygulamalarında kullanabilirsiniz.

Yansıtma kullanan diğer bağımlılık ekleme çerçeveleri, kodunuzu ek açıklamalar için tarayarak işlemleri başlatır. 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. Bu kitaplıklarda istediğiniz özellikler 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.