Süreçlere ve ileti dizilerine genel bakış

Bir uygulama bileşeni başlatıldığında ve uygulamada çalışan başka bileşen olmadığında Android sistemi, uygulama için tek bir yürütme iş parçacığına sahip yeni bir Linux süreci başlatır. Varsayılan olarak, aynı uygulamanın tüm bileşenleri aynı işlem ve iş parçacığında (ana iş parçacığı) çalışır.

Bir uygulama bileşeni başlatıldığında ve uygulamanın başka bir bileşeni zaten başlatıldığı için bu uygulama için halihazırda bir işlem varsa bileşen bu işlem içinde başlatılır ve aynı yürütme iş parçacığını kullanır. Ancak, uygulamanızdaki farklı bileşenlerin ayrı işlemler halinde çalışmasını sağlayabilir ve herhangi bir işlem için ek iş parçacıkları oluşturabilirsiniz.

Bu belgede, Android uygulamalarında işlemlerin ve iş parçacıklarının nasıl çalıştığı açıklanmaktadır.

İşlemler

Varsayılan olarak, bir uygulamanın tüm bileşenleri aynı işlemde çalışır ve çoğu uygulama bunu değiştirmez. Ancak belirli bir bileşenin hangi işleme ait olduğunu kontrol etmeniz gerektiğini düşünüyorsanız bunu manifest dosyasında yapabilirsiniz.

Her tür bileşen öğesi (<activity>, <service>, <receiver> ve <provider>) için manifest girişi, bileşenin çalışacağı süreci belirtebilen bir android:process özelliğini destekler. Bu özelliği, her bileşen kendi sürecinde çalışacak veya bazı bileşenler bir süreci paylaşırken diğerleri paylaşmayacak şekilde ayarlayabilirsiniz.

Ayrıca, uygulamaların aynı Linux kullanıcı kimliğini paylaşması ve aynı sertifikalarla imzalanması koşuluyla, farklı uygulamaların bileşenlerinin aynı süreçte çalışmasını sağlayacak şekilde de ayarlayabilirsiniz.android:process

<application> öğesi, tüm bileşenler için geçerli olan bir varsayılan değer ayarlamak üzere kullanabileceğiniz bir android:process özelliğini de destekler.

Android, kaynaklar kullanıcıya daha doğrudan hizmet veren diğer işlemler tarafından gerektiğinde bir işlemi kapatmaya karar verebilir. Kapatılan süreçte çalışan uygulama bileşenleri de buna bağlı olarak yok edilir. Bu bileşenlerin yapması gereken bir iş olduğunda işlem yeniden başlatılır.

Android sistemi, hangi işlemlerin kapatılacağına karar verirken bu işlemlerin kullanıcı için önemini göz önünde bulundurur. Örneğin, ekranda artık görünmeyen etkinliklere ev sahipliği yapan bir işlemi, görünür etkinliklere ev sahipliği yapan bir işleme kıyasla daha kolay kapatır. Bu nedenle, bir işlemi sonlandırma kararı, söz konusu işlemde çalışan bileşenlerin durumuna bağlıdır.

Süreç yaşam döngüsünün ayrıntıları ve uygulama durumlarıyla ilişkisi Süreçler ve uygulama yaşam döngüsü bölümünde ele alınmıştır.

İleti Dizileri

Bir uygulama başlatıldığında sistem, uygulama için ana iş parçacığı adı verilen bir yürütme iş parçacığı oluşturur. Bu iş parçacığı, çizim etkinlikleri de dahil olmak üzere etkinlikleri uygun kullanıcı arayüzü widget'larına göndermekten sorumlu olduğundan çok önemlidir. Ayrıca, uygulamanızın Android kullanıcı arayüzü araç setinin android.widget ve android.view paketlerindeki bileşenlerle etkileşimde bulunduğu iş parçacığı da neredeyse her zaman budur. Bu nedenle, ana iş parçacığına bazen kullanıcı arayüzü iş parçacığı da denir. Ancak özel durumlarda bir uygulamanın ana iş parçacığı, kullanıcı arayüzü iş parçacığı olmayabilir. Daha fazla bilgi için İş parçacığı açıklamaları başlıklı makaleyi inceleyin.

Sistem, bir bileşenin her örneği için ayrı bir ileti dizisi oluşturmaz. Aynı süreçte çalışan tüm bileşenler kullanıcı arayüzü iş parçacığında oluşturulur ve her bileşene yapılan sistem çağrıları bu iş parçacığından gönderilir. Sonuç olarak, sistem geri çağırmalarına yanıt veren yöntemler (ör. kullanıcı işlemlerini bildirmek için onKeyDown() veya bir yaşam döngüsü geri çağırma yöntemi) her zaman işlemin kullanıcı arayüzü iş parçacığında çalışır.

Örneğin, kullanıcı ekranda bir düğmeye dokunduğunda uygulamanızın kullanıcı arayüzü iş parçacığı, dokunma etkinliğini widget'a gönderir. Widget da basılı durumunu ayarlar ve etkinlik kuyruğuna bir geçersiz kılma isteği gönderir. Kullanıcı arayüzü iş parçacığı, isteği kuyruktan çıkarır ve widget'ı kendini yeniden çizmesi için bilgilendirir.

Uygulamanızı düzgün bir şekilde uygulamadığınız sürece bu tek iş parçacıklı model, uygulamanız kullanıcı etkileşimine yanıt olarak yoğun bir çalışma yaptığında düşük performans gösterebilir. Kullanıcı arayüzü iş parçacığında ağ erişimi veya veritabanı sorguları gibi uzun işlemlerin yapılması, kullanıcı arayüzünün tamamının engellenmesine neden olur. İş parçacığı engellendiğinde çizim etkinlikleri de dahil olmak üzere hiçbir etkinlik gönderilemez.

Kullanıcı açısından uygulama yanıt vermeyi durdurmuş gibi görünür. Daha da kötüsü, kullanıcı arayüzü iş parçacığı birkaç saniyeden uzun süre engellenirse kullanıcıya "Uygulama yanıt vermiyor" (ANR) iletişim kutusu gösterilir. Kullanıcı daha sonra uygulamanızdan çıkmaya veya uygulamayı kaldırmaya karar verebilir.

Android kullanıcı arayüzü araç kitinin iş parçacığı açısından güvenli olmadığını unutmayın. Bu nedenle, kullanıcı arayüzünüzü bir çalışan iş parçacığından değiştirmeyin. Kullanıcı arayüzünüzde tüm işlemleri kullanıcı arayüzü iş parçacığından yapın. Android'in tek iş parçacıklı modelinde iki kural vardır:

  1. Kullanıcı arayüzü iş parçacığını engellemeyin.
  2. Android kullanıcı arayüzü araç setine kullanıcı arayüzü iş parçacığı dışından erişmeyin.

Çalışan iş parçacıkları

Bu tek iş parçacıklı model nedeniyle, uygulamanızın kullanıcı arayüzünün yanıt verme hızını korumak için kullanıcı arayüzü iş parçacığını engellememeniz çok önemlidir. Anında gerçekleşmeyen işlemleriniz varsa bunları ayrı arka plan veya çalışan iş parçacıklarında yaptığınızdan emin olun. Kullanıcı arayüzünü, kullanıcı arayüzü iş parçacığı veya ana iş parçacığı dışındaki iş parçacıklarından güncelleyemeyeceğinizi unutmayın.

Android, bu kurallara uymanıza yardımcı olmak için kullanıcı arayüzü iş parçacığına diğer iş parçacıklarından erişmenin çeşitli yollarını sunar. Size yardımcı olabilecek yöntemlerin listesini aşağıda bulabilirsiniz:

Aşağıdaki örneklerde, bir görevin arka plan iş parçacığına nasıl aktarılacağı ve görev tamamlandıktan sonra kullanıcı arayüzü iş parçacığının nasıl güncelleneceği gösterilmektedir:

Kotlin

// Kotlin coroutines implementation.
fun onClick(v: View) {
    // Launch a coroutine in the lifecycle scope (e.g., in an Activity or Fragment).
    lifecycleScope.launch {
        // Run the blocking task on the IO dispatcher.
        val bitmap = withContext(Dispatchers.IO) {
            BitmapFactory.decodeFile("image.png")
        }
        // Back on the main thread, update the UI.
        imageView.setImageBitmap(bitmap)
    }
}

Java

// Java Executor implementation.
// (executorService is assumed to be defined elsewhere).
public void onClick(View v) {
    executorService.execute(() -> {
        // Run the heavy task on a background thread.
        Bitmap bitmap = BitmapFactory.decodeFile("image.png");

        // Update the View on the UI thread.
        imageView.post(() -> imageView.setImageBitmap(bitmap));
    });
}

Arka plan işlemi ayrı bir iş parçacığından yapılırken ImageView her zaman kullanıcı arayüzü iş parçacığından değiştirildiğinden bu uygulama iş parçacığı açısından güvenlidir.

Ancak işlemin karmaşıklığı arttıkça bu tür kodlar karmaşık hale gelebilir ve bakımı zorlaşabilir. Bir çalışan iş parçacığıyla daha karmaşık etkileşimleri işlemek için, kullanıcı arayüzü iş parçacığından gönderilen mesajları işlemek üzere çalışan iş parçacığınızda Handler kullanmayı düşünebilirsiniz. Arka plan iş parçacıklarında çalışmayı planlama ve kullanıcı arayüzü iş parçacığına geri iletişim kurma hakkında ayrıntılı açıklama için Arka Plan Çalışmasına Genel Bakış başlıklı makaleyi inceleyin.

İş parçacığı güvenli yöntemler

Bazı durumlarda, uyguladığınız yöntemler birden fazla iş parçacığından çağrılır ve bu nedenle iş parçacığı açısından güvenli olacak şekilde yazılmalıdır.

Bu durum, özellikle uzaktan çağrılabilen yöntemler (ör. bağlı hizmetlerdeki yöntemler) için geçerlidir. IBinder içinde uygulanan bir yöntemde yapılan çağrı, IBinder'nin çalıştığı süreçte gerçekleştiğinde yöntem, arayanın iş parçacığında yürütülür. Ancak arama başka bir işlemde başlatıldığında yöntem, sistemin IBinder ile aynı işlemde tuttuğu bir iş parçacığı havuzundan seçilen bir iş parçacığında yürütülür. İşlemin kullanıcı arayüzü iş parçacığında yürütülmez.

Örneğin, bir hizmetin onBind() yöntemi hizmetin işleminin kullanıcı arayüzü iş parçacığından çağrılırken onBind() tarafından döndürülen nesnede uygulanan yöntemler (ör. uzak prosedür çağrısı (RPC) yöntemlerini uygulayan bir alt sınıf) havuzdaki iş parçacıklarından çağrılır. Bir hizmetin birden fazla istemcisi olabileceğinden, aynı IBinder yöntemiyle aynı anda birden fazla havuz iş parçacığı etkileşime girebilir. Bu nedenle, IBinder yöntemleri iş parçacığı güvenli olacak şekilde uygulanmalıdır.

Benzer şekilde, bir içerik sağlayıcı başka süreçlerden kaynaklanan veri istekleri alabilir. ContentResolver ve ContentProvider sınıfları, süreçler arası iletişimin (IPC) nasıl yönetildiğine dair ayrıntıları gizler. Ancak bu isteklere yanıt veren ContentProvider yöntemleri (query(), insert(), delete(), update() ve getType() yöntemleri) sürecin kullanıcı arayüzü iş parçacığı yerine içerik sağlayıcının sürecindeki bir iş parçacığı havuzundan çağrılır. Bu yöntemler aynı anda herhangi bir sayıda iş parçacığından çağrılabileceğinden, iş parçacığı açısından güvenli olacak şekilde uygulanmalıdır.

İşlemler arası iletişim

Android, RPC'leri kullanarak IPC için bir mekanizma sunar. Bu mekanizmada bir yöntem, etkinlik veya başka bir uygulama bileşeni tarafından çağrılır ancak uzaktan başka bir işlemde yürütülür. Sonuçlar ise arayana geri döndürülür. Bu işlem, bir yöntem çağrısını ve verilerini işletim sisteminin anlayabileceği bir düzeye kadar ayrıştırmayı, yerel işlem ve adres alanından uzak işlem ve adres alanına iletmeyi, ardından da çağrıyı orada yeniden birleştirmeyi ve yeniden etkinleştirmeyi içerir.

Döndürülen değerler daha sonra ters yönde iletilir. Android, bu IPC işlemlerini gerçekleştirmek için gereken tüm kodu sağlar. Böylece RPC programlama arayüzünü tanımlamaya ve uygulamaya odaklanabilirsiniz.

IPC gerçekleştirmek için uygulamanızın bindService() kullanarak bir hizmete bağlanması gerekir. Daha fazla bilgi için Hizmetlere genel bakış başlıklı makaleyi inceleyin.