Android'de ileti dizilerini doğru şekilde kullanmak, uygulamanızın performansını artırmanıza yardımcı olabilir. bazı yolları da görmüştük. Bu sayfada, ileti dizileriyle çalışmanın çeşitli yönleri ele alınmaktadır: kullanıcı arayüzü veya ana iş parçacığı ile çalışma; uygulama yaşam döngüsü ile ileti dizisi önceliği; ve platformun iş parçacığının yönetilmesine yardımcı olmak için sağladığı yöntemler gerekir. Bu alanların her birinde, bu sayfada olası tehlikeler ve stratejilere değineceğiz.
Ana iş parçacığı
Kullanıcı, uygulamanızı başlattığında Android, yeni bir Linux oluşturur süreciyle birlikte gösterir. Bu ana ileti dizisinde, UI iş parçacığı olarak da bilinir, gerçekleşen her şeyden ekranda görebilirsiniz. Nasıl çalıştığını anlamak, uygulamanızı ana ileti dizisi geliştirmenizi sağlar.
Dahililer
Ana iş parçacığı çok basit bir tasarıma sahip: Tek işi, alan adını alıp İş parçacığı açısından güvenli bir iş sırasından, uygulaması sonlandırılana kadar yapılan iş blokları. İlgili içeriği oluşturmak için kullanılan bu çalışma bloklarının bazılarını çeşitli kaynaklardan oluşturur. Bu yerler, yaşam döngüsü bilgileriyle ilişkili geri çağırmaları, veya diğer uygulama ya da işlemlerden gelen etkinlikler olarak tanımlar. Ayrıca uygulama blokları kendi başlarına, çerçeveyi kullanmadan açıkça kuyruğa sokabilir.
Neredeyse tüm uygulamanızın yürüttüğü kod bloğu bir etkinlik geri çağırmasına bağlıdır (örneğin, giriş, veya çizim kullanabilirsiniz. Bir şey tetiklendiğinde, etkinliğin gerçekleştiği ileti dizisi etkinliği kendi dışına iter ve ana ileti dizisinin iletisine sıra. Böylece ana iş parçacığı etkinliğe hizmet verebilir.
Bir animasyon veya ekran güncellemesi gerçekleşirken sistem bir animasyon veya ekran güncellemesi her 16 ms’de bir (ekranın çiziminden sorumlu olan) bir iş bloku oluşturmak için 60. saniyede kare/saniye sayısı. Sistemin bu hedefe ulaşması için Kullanıcı Arayüzü/Görünüm hiyerarşisi ana ileti dizisinde güncellenmesi gerekir. Ancak ana ileti dizisinin mesajlaşma sırasında ana iş parçacığının göremeyeceği kadar çok veya çok uzun olan görevler içerir. güncellemeyi yeterince hızlı bir şekilde tamamlarsa uygulama bu çalışmayı bir çalışana ileti dizisi. Ana iş parçacığı, iş bloklarını yürütmeyi 16 ms içinde bitiremezse Kullanıcı, girişte takılma, gecikme veya kullanıcı arayüzünün yanıt verme yeteneğinin zayıf olduğunu fark edebilir. Ana iş parçacığı yaklaşık beş saniye boyunca engellenirse sistem, Uygulama Kullanıcının uygulamayı doğrudan kapatmasına olanak tanıyan Yanıt Vermiyor (ANR) iletişim kutusu.
Çok sayıda veya uzun görevi, ana iş parçacığından engellememeleri için taşıma Kolay oluşturma ve kullanıcı girişine hızlı yanıt verme özellikleri, Bunun için Android'i kullanabilirsiniz.
İleti dizileri ve kullanıcı arayüzü nesne referansları
Tasarım gereği, Android Görünüm nesneleri iş parçacığı açısından güvenli değil. Bir uygulamanın oluşturması, kullanması ve kullanıcı arayüzü nesnelerini yok edin. Bir önceki videoda hatta ana iş parçacığı dışında bir iş parçacığında bir UI nesnesine referansta bulunursanız istisnalar, sessiz hatalar, kilitlenmeler ve tanımlanmamış diğer hatalı davranışlar olabilir.
Referanslarla ilgili sorunlar iki farklı kategoriye ayrılır: açık referanslar hem de örtülü referanslar.
Uygunsuz referanslar
Ana olmayan iş parçacıklarındaki birçok görevin nihai hedefi, kullanıcı arayüzü nesnelerini güncellemektir. Ancak bu iş parçacıklarından biri görünüm hiyerarşisindeki bir nesneye erişirse uygulama kararsızlığı ortaya çıkabilir: Bir çalışan iş parçacığının başka bir iş parçacığının nesneye referansta bulunduğu sırada bu nesneyi sonuçlar tanımlanmadı.
Örneğin, bir kullanıcı arayüzü nesnesine doğrudan referans içeren bir uygulama
çalışan iş parçacığı. Çalışan iş parçacığındaki nesne,
View
; ancak iş tamamlanmadan önce View
görünüm hiyerarşisinden kaldırılır. Bu iki işlem aynı anda gerçekleştiğinde
referans, View
nesnesini bellekte tutar ve nesne üzerindeki özellikleri ayarlar.
Ancak, kullanıcı
başvuru kaldırıldıktan sonra uygulama nesneyi siler.
Başka bir örnekte, View
nesneleri etkinliğe ilişkin referanslar içeriyor
sahibi olan kullanıcılara aitti. Eğer
ancak etkinliğin son haline geldiğini ancak
doğrudan veya dolaylı olarak başvuruda bulunduğu için çöp toplayıcı
yürütülmesi bitene kadar işleme devam eder.
Bu senaryo, dizi halinde çalışmanın bulunduğu durumlarda bir soruna
bazı etkinlik yaşam döngüsü etkinlikleri (ör. ekran döndürme) gerçekleşirken uçuşun bir kısmını takip edin.
Sistem, yayın yapana kadar atık toplama işlemi gerçekleştiremez
yardımcı olur. Sonuç olarak, içinde iki Activity
nesne olabilir
bellekte kalmasını sağlar.
Buna benzer senaryolarda uygulamanızda uygunsuz içerik barındırmamasını öneririz iş parçacıklı iş görevlerindeki kullanıcı arayüzü nesnelerine yapılan referanslar. Bu tür referanslardan kaçınmak, bir projeyi yürütmek için iş parçacığı anlaşmazlığından uzak durmaya çalışacak.
Her durumda, uygulamanız yalnızca ana iş parçacığındaki kullanıcı arayüzü nesnelerini güncellemelidir. Bu birden çok iş parçacığının aşağıdakileri yapmasına izin veren bir görüşme politikası en önemli etkinliği veya en önemli aktiviteyi içeren ana ileti dizisine öğesini kullanın.
Dolaylı referanslar
İş parçacıklı nesnelerde yaygın olarak görülen bir kod tasarımı hatası, aşağıdaki kodu kullanabilirsiniz:
Kotlin
class MainActivity : Activity() { // ... inner class MyAsyncTask : AsyncTask<Unit, Unit, String>() { override fun doInBackground(vararg params: Unit): String {...} override fun onPostExecute(result: String) {...} } }
Java
public class MainActivity extends Activity { // ... public class MyAsyncTask extends AsyncTask<Void, Void, String> { @Override protected String doInBackground(Void... params) {...} @Override protected void onPostExecute(String result) {...} } }
Bu snippet'teki kusur, kodun iş parçacığı nesnesini tanımlamasıdır.
Bazı etkinliklerin (veya iç sınıfın) statik olmayan iç sınıfı olarak MyAsyncTask
). Bu beyan, ek Activity
öğesine örtülü bir referans oluşturuyor
kullanır. Sonuç olarak nesne,
ileti dizisindeki çalışmaların tamamlanması, referans verilen etkinliğin kaldırılmasında gecikmeye neden olur.
Bu gecikme de hafıza üzerinde daha fazla baskı yaratır.
Bu soruna doğrudan bir çözüm, aşırı yüklenen sınıfınızı tanımlamaktır. ya da kendi dosyalarında sınıflandırmayı sağlayan örnekler içerir. Böylece, örtülü referanstır.
Diğer bir çözüm de arka plan görevlerini her zaman iptal edip uygun
Activity
yaşam döngüsü geri çağırması (ör. onDestroy
). Bu yaklaşım,
ve hataya açıktır. Genel bir kural olarak, kullanıcı arayüzü dışında karmaşık ve
doğrudan inceleyebiliyor. Ayrıca, AsyncTask
artık kullanımdan kaldırıldı ve
yeni kodda kullanılması önerilmez. Android'de Threading (Android'de Threading) bölümüne göz atın.
inceleyin.
İleti dizileri ve uygulama etkinliği yaşam döngüleri
Uygulama yaşam döngüsü, iş parçacıklarının uygulamanızda çalışma şeklini etkileyebilir. Bir ileti dizisinin etkinlik yok sayılır. Bununla birlikte, proje hedefleri ile ileti dizisi önceliklendirme ve bir etkinliğin ön planda mı yoksa arka plan.
Devam eden ileti dizileri
İleti dizileri, bunları oluşturan etkinliklerin ömrü boyunca var olur. Mesaj dizileri yaratılmasından veya ortadan kaldırılmasından bağımsız olarak, kesintisiz olarak devam etmek için gerekli işlemler yapılmadığında, başvuru süreciyle birlikte sonlandırılır. daha etkin uygulama bileşenleri içerir. Bazı durumlarda bu sebat istenen bir durumdur.
Bir etkinliğin dizili iş blokları oluşturduğu bir örneği düşünün. ardından bir çalışan iş parçacığı blokları yürütmeden önce kaldırılır. Uygulama ne gibi bir uygulama söz konusu?
Bloklar artık mevcut olmayan bir kullanıcı arayüzünü güncelleyecekse bunun bir nedeni yoktur. devam etmesi için ekibi teşvik etmek içindir. Örneğin, çalışma olarak kullanıcı bilgilerinin yüklenmesi görünümlerini güncellerseniz ileti dizisine artık gerek kalmaz.
Bunun aksine, çalışma paketlerinin kapsamı dışında kalan
Kullanıcı arayüzü. Bu durumda, ileti dizisini sürdürmeniz gerekir. Örneğin, paketler
bir görüntüyü indirmek, diskte önbelleğe almak ve ilişkili
View
nesne algılandı. Nesne artık mevcut olmasa da, indirme ve
resmin önbelleğe alınması, kullanıcının sayfaya geri dönmesi ihtimaline karşı
etkinliği yok etti.
Tüm iş parçacığı nesneleri için yaşam döngüsü yanıtlarının manuel olarak yönetilmesi
karmaşık hale getirebilirsiniz. Bu kuralları doğru şekilde yönetmezseniz uygulamanız
ve performans sorunları olduğunu
unutmayın. Şunları birleştirme:
ViewModel
LiveData
ile şunları yapabilirsiniz:
verileri yükle ve değişiklik olduğunda bildirim alın
endişelenmenize gerek yok.
ViewModel
nesne
tek bir çözüm olduğunu düşünebilir. ViewModel'ler,
görüntüleme verilerinizi saklamanız için kolay bir yol sunar. ViewModels hakkında daha fazla bilgi için
ViewModel rehberini inceleyin ve
LiveData, LiveData kılavuzuna bakın. Şu durumda:
uygulama mimarisi hakkında daha fazla bilgi edinmek isterseniz
Uygulama Mimarisi Kılavuzu.
İleti dizisi önceliği
İşlemler ve Uygulama Yaşam Döngüsü gibi düşünebilirsiniz. kısmen uygulamanın yaşam döngüsünde nerede bulunduğuna bağlıdır. Projeyi oluştururken ve ileti dizilerini yönetmeniz gerekiyorsa, ileti dizilerinin önceliklerini doğru ileti dizilerinin doğru zamanda doğru öncelikleri alması. Çok yüksek bir değere ayarlanırsa iş parçacığınız UI iş parçacığını ve RenderThread'i kesintiye uğratarak uygulamanızın çerçeveleri kullanabilirsiniz. Çok düşük bir değere ayarlanırsa eşzamansız görevlerinizi (ör. daha yavaş olabilir.
Her ileti dizisi oluşturduğunuzda
setThreadPriority()
Sistemin iş parçacığı
planlayıcı, yüksek öncelikli ileti dizilerine öncelik verir ve bunları
ve öncelikleri netleştirmeye
odaklanmasına yardımcı olur. Genellikle ileti dizileri
ön planda
grup, toplam yürütme süresinin yaklaşık%95'ini,
arka plan grubu yaklaşık %5 olur.
Sistem ayrıca
Process
sınıf.
Varsayılan olarak sistem, ileti dizisinin önceliğini aynı önceliğe ve gruba ayarlar
üyelik satın alabilirsiniz. Ancak uygulamanız,
ileti dizisi önceliğini
setThreadPriority()
Process
sınıfının, en yüksek alaka düzeyine sahip olmasının yanı sıra,
uygulamanızın, iş parçacığı önceliklerini belirlemek için kullanabileceği sabit değerler kümesi. Örneğin,
THREAD_PRIORITY_DEFAULT
.
bir ileti dizisinin varsayılan değerini temsil eder. Uygulamanız ileti dizisinin önceliğini şu şekilde ayarlamalıdır:
THREAD_PRIORITY_BACKGROUND
.
.
Uygulamanız THREAD_PRIORITY_LESS_FAVORABLE
ile kullanılabilir
ve THREAD_PRIORITY_MORE_FAVORABLE
sabitleri artımlı şekilde ayarlayabilirsiniz. Şunlar için:
ileti dizilerinin önceliklerini
Şu değerde THREAD_PRIORITY
sabit değer:
Process
sınıfı.
Daha fazla bilgi için
daha fazla bilgi edinmek için aşağıdaki referans belgelerine
Thread
ve Process
sınıf.
İleti dizisi oluşturma için yardımcı sınıfları
Birincil dili olarak Kotlin'i kullanan geliştiriciler eş yordamları kullanmalarını öneririz. Eş yordamlar, geri çağırma olmadan eşzamansız kod yazma ve kapsam oluşturma, iptal ve hata işleme için yapılandırılmış eşzamanlılık sağlar.
Bu çerçeve, aynı Java sınıflarını ve temel öğelerini sağlayarak
ileti dizisi (ör. Thread
, Runnable
)
ve Executors
sınıf varsa
ve HandlerThread
gibi başka uzantılar da dahil edilir.
Daha fazla bilgi için Android'de İleti Dizisi Oluşturma konusuna bakın.
HandlerThread sınıfı
İşleyici iş parçacığı, bir kuyruktaki işleri alan ve çalışan bir iş parçacığıdır. tıklayın.
Cihazınızdan önizleme kareleri almayla ilgili sık karşılaşılan
Camera
nesne algılandı.
Kamera önizleme çerçeveleri için kaydolduğunuzda, bu çerçeveleri
onPreviewFrame()
.
geri çağırması, çağrının yapıldığı etkinlik ileti dizisinde çağrılır. Bu
büyük pikselle ilgilenme görevi, kullanıcı arayüzü iş parçacığında geri çağırma
oluşturma ve etkinlik işleme çalışmalarını etkileyebilir.
Bu örnekte, uygulamanız Camera.open()
komutunu bir kullanıcıya
işleyici iş parçacığındaki iş bloğu, ilişkili
onPreviewFrame()
geri arama
kullanıcı arayüzü iş parçacığı yerine işleyici iş parçacığına çıkar. Uzun süreli çalışma için
çalıştığında, bu sizin için daha iyi bir çözüm olabilir.
Uygulamanız HandlerThread
kullanarak bir ileti dizisi oluşturduğunda
ileti dizisinin
önceliklerini belirleyebilirsiniz. Unutmayın, CPU'lar yalnızca
az sayıda iş parçacığının paralel olarak işlenmesini sağlar. Öncelikleri belirlemek,
sistem bu çalışmayı planlayacak doğru yolları bilir:
dikkat çekmek için mücadele ediyor.
ThreadPoolExecutor sınıfı
Bazı iş türleri büyük oranda paralel
olarak incelenebilir,
ya da dağıtılmış görevleri de
göz önünde bulundurmalısınız. Örneğin, bu tür bir görev her bir filtre için
8 megapiksellik bir resimden oluşan 8x8 blok. İş paketlerinin hacminin oldukça yüksek olması
oluşturuyorsa HandlerThread
, kullanılması uygun bir sınıf değildir.
ThreadPoolExecutor
, şu konulara yardımcı olacak bir sınıftır:
kolaylaştıracaktır. Bu sınıf, bir ileti dizisi grubunun,
ve çalışmanın bu ileti dizileri arasında nasıl dağıtıldığını yönetir.
İş yükü arttıkça veya azaldıkça sınıf hızlanır ya da daha fazla ileti dizisini kaldırır.
iş yüküne uyum sağlamasıdır.
Bu sınıf, uygulamanızın optimum sayıda iş parçacığı üretmesine de yardımcı olur. Zaman
bir ThreadPoolExecutor
oluşturur
nesne olursa, uygulama bir minimum ve maksimum
iş parçacığı sayısı. Projeye verilen iş yükü olarak
ThreadPoolExecutor
artıyor,
ve en iyi iş parçacıklarının sayısını hesaplamak için
ve bekleyen iş miktarını göz önünde
bulundurmanız gerekir. Bunları temel alarak
nasıl faktör olacağına ThreadPoolExecutor
karar verir.
ileti dizileri her zaman yayında olmalıdır.
Kaç ileti dizisi oluşturmanız gerekir?
Yazılım düzeyinde olsa da, kodunuz, yüzlerce Aksi takdirde performans sorunlarıyla karşılaşabilirsiniz. Uygulamanız sınırlı CPU'ya sahip arka plan hizmetleri, oluşturucu, ses motoru ve birçok işlevi vardır. CPU'lar aslında yalnızca az sayıda iş parçacığını paralel olarak işleyebilme; üzerinde çalışan her şey öncelik ve planlama sorunlarına değineceğiz. Bu nedenle, yalnızca ihtiyaç duyduğunuz kadar iş parçacığı oluşturabilirsiniz.
Pratikte bunun için birçok değişken var ancak bir değer seçme (örneğin, ilk olarak 4) ve onu Systrace: kesinlikle güçlü bir stratejidir. Cevaplarınızı en üst düzeye çıkarmak için deneme yanılma yöntemini sorun yaşamadan kullanabileceğiniz minimum ileti dizisi sayısı.
Kaç ileti dizisine sahip olacağınıza karar verirken dikkate almanız gereken diğer bir nokta da bunlar hafızada yer kaplar. Her iş parçacığının en az 64 k bellek maliyeti vardır. Bu, bir cihazda yüklü olan birçok uygulama arasında, özellikle de önemli ölçüde büyüdüğü durumlar için geçerlidir.
Birçok sistem işlemi ve üçüncü taraf kitaplığı genellikle kendi ileti dizileri. Uygulamanız mevcut bir ileti dizisi havuzunu yeniden kullanabiliyorsa bu yeniden kullanım yöntemi yardımcı olabilir performansı artırır.