Süreçler arasında iletişim kurmak için bağlayıcı kullanırken, uzak süreç önbelleğe alınmış veya dondurulmuş durumdayken özel dikkat gösterin. Önbelleğe alınmış veya dondurulmuş uygulamalara yapılan aramalar, bu uygulamaların kilitlenmesine veya gereksiz yere kaynak tüketmesine neden olabilir.
Önbelleğe alınmış ve dondurulmuş uygulama durumları
Android, bellek ve CPU gibi sistem kaynaklarını yönetmek için uygulamaları farklı durumlarda tutar.
Önbelleğe alınmış durum
Etkinlikler veya hizmetler gibi kullanıcı tarafından görülebilen bileşenleri olmayan uygulamalar önbelleğe alınmış duruma taşınabilir. Ayrıntılı bilgi için Süreçler ve uygulama yaşam döngüsü başlıklı makaleyi inceleyin. Önbelleğe alınan uygulamalar, kullanıcının tekrar kullanması ihtimaline karşı bellekte tutulur ancak aktif olarak çalışması beklenmez.
Bir uygulama işleminden diğerine bağlama işlemi (ör. bindService kullanma) gerçekleştirildiğinde, sunucu işleminin işlem durumu, istemci işlemi kadar önemli olacak şekilde yükseltilir (Context#BIND_WAIVE_PRIORITY belirtildiği durumlar hariç). Örneğin, istemci önbelleğe alınmış durumda değilse sunucu da önbelleğe alınmış durumda değildir.
Aksine, bir sunucu işleminin durumu istemcilerinin durumunu belirlemez. Bu nedenle, bir sunucunun istemcilerle bağlayıcı bağlantıları olabilir (en yaygın olarak geri çağırma biçiminde) ve uzak işlem önbelleğe alınmış durumdayken sunucu önbelleğe alınmaz.
Geri çağırmaların yükseltilmiş bir süreçte başladığı ve uygulamalara teslim edildiği API'ler tasarlarken, bir uygulama önbelleğe alınmış duruma girdiğinde geri çağırmaların gönderimini duraklatmayı ve bu durumdan çıktığında devam ettirmeyi göz önünde bulundurun. Bu, önbelleğe alınmış uygulama işlemlerinde gereksiz çalışmayı önler.
Uygulamaların ne zaman önbelleğe alınmış duruma girdiğini veya bu durumdan çıktığını izlemek için ActivityManager.addOnUidImportanceListener kullanın:
Java
// in ActivityManager or Context
activityManager.addOnUidImportanceListener(
new ActivityManager.OnUidImportanceListener() { ... },
IMPORTANCE_CACHED);
Kotlin
// in ActivityManager or Context
activityManager.addOnUidImportanceListener({ uid, importance ->
// ...
}, IMPORTANCE_CACHED)
Dondurulmuş durum
Sistem, kaynakları korumak için önbelleğe alınmış bir uygulamayı dondurabilir. Dondurulan uygulamalar CPU süresi almaz ve herhangi bir işlem yapamaz. Daha fazla bilgi için Önbelleğe alınmış uygulamaları dondurma başlıklı makaleyi inceleyin.
Bir işlem, dondurulmuş başka bir uzak işleme senkronize (oneway değil) bağlayıcı işlemi gönderdiğinde sistem, uzak işlemi sonlandırır. Bu, arama işlemindeki arama iş parçacığının, uzak işlemin dondurulmasının çözülmesini beklerken süresiz olarak askıda kalmasını önler. Bu durum, arama uygulamasında iş parçacığı açlığına veya kilitlenmelere neden olabilir.
Bir işlem, dondurulmuş bir uygulamaya (genellikle bir geri çağırma bildirerek, bu da genellikle bir oneway yöntemidir) eşzamansız (oneway) bağlayıcı işlemi gönderdiğinde, işlem uzak işlem dondurulana kadar arabelleğe alınır. Arabellek taşarsa alıcı uygulama işlemi kilitlenebilir. Ayrıca, arabelleğe alınmış işlemler, uygulama işlemi dondurulması kaldırılıp bu işlemleri gerçekleştirene kadar eski hale gelebilir.
Uygulamaların eski etkinliklerle aşırı yüklenmesini veya arabelleklerinin dolmasını önlemek için alıcı uygulamanın işlemi dondurulmuşken geri çağırma işlemlerinin gönderilmesini duraklatmanız gerekir.
Uygulamaların ne zaman dondurulduğunu veya çözüldüğünü takip etmek için
IBinder.addFrozenStateChangeCallback kullanın:
Java
// The binder token of the remote process
IBinder binder = service.getBinder();
// Keep track of frozen state
AtomicBoolean remoteFrozen = new AtomicBoolean(false);
// Update remoteFrozen when the remote process freezes or unfreezes
binder.addFrozenStateChangeCallback(
myExecutor,
new IBinder.FrozenStateChangeCallback() {
@Override
public void onFrozenStateChanged(boolean isFrozen) {
remoteFrozen.set(isFrozen);
}
});
// When dispatching callbacks to the remote process, pause dispatch if frozen:
if (!remoteFrozen.get()) {
// dispatch callback to remote process
}
Kotlin
// The binder token of the remote process
val binder: IBinder = service.getBinder()
// Keep track of frozen state
val remoteFrozen = AtomicBoolean(false)
// Update remoteFrozen when the remote process freezes or unfreezes
binder.addFrozenStateChangeCallback(myExecutor) { isFrozen ->
remoteFrozen.set(isFrozen)
}
// When dispatching callbacks to the remote process, pause dispatch if frozen:
if (!remoteFrozen.get()) {
// dispatch callback to remote process
}
C++
C++ bağlayıcı API'lerini kullanan platform kodu için:
#include <binder/Binder.h>
#include <binder/IBinder.h>
// The binder token of the remote process
android::sp<android::IBinder> binder = service->getBinder();
// Keep track of frozen state
std::atomic<bool> remoteFrozen = false;
// Define a callback class
class MyFrozenStateCallback : public android::IBinder::FrozenStateChangeCallback {
public:
explicit MyFrozenStateCallback(std::atomic<bool>* frozenState) : mFrozenState(frozenState) {}
void onFrozenStateChanged(bool isFrozen) override {
mFrozenState->store(isFrozen);
}
private:
std::atomic<bool>* mFrozenState;
};
// Update remoteFrozen when the remote process freezes or unfreezes
if (binder != nullptr) {
binder->addFrozenStateChangeCallback(android::sp<android::IBinder::FrozenStateChangeCallback>::make(
new MyFrozenStateCallback(&remoteFrozen)));
}
// When dispatching callbacks to the remote process, pause dispatch if frozen:
if (!remoteFrozen.load()) {
// dispatch callback to remote process
}
RemoteCallbackList'i kullanma
RemoteCallbackList sınıfı, uzak işlemlerin kaydettiği IInterface geri çağırma listelerini yönetmeye yardımcı olur. Bu sınıf, bağlayıcı sonlandırma bildirimlerini otomatik olarak işler ve dondurulmuş uygulamalara geri çağırmaları işlemek için seçenekler sunar.
RemoteCallbackList oluştururken dondurulmuş bir aranan politikası belirtebilirsiniz:
FROZEN_CALLEE_POLICY_DROP: Dondurulmuş uygulamalara yapılan geri aramalar sessizce bırakılır. Uygulama önbelleğe alınmışken gerçekleşen etkinlikler (ör. gerçek zamanlı sensör etkinlikleri) uygulama için önemli olmadığında bu politikayı kullanın.FROZEN_CALLEE_POLICY_ENQUEUE_MOST_RECENT: Bir uygulama dondurulmuşken birden fazla geri çağırma yayınlanırsa yalnızca en sonuncusu sıraya alınır ve uygulama dondurulması kaldırıldığında teslim edilir. Bu, yalnızca en son durum güncellemesinin önemli olduğu duruma dayalı geri çağırmalar için kullanışlıdır. Örneğin, uygulamaya mevcut medya sesini bildiren bir geri çağırma.FROZEN_CALLEE_POLICY_ENQUEUE_ALL: Bir uygulama dondurulmuş durumdayken yayınlanan tüm geri çağırmalar sıraya alınır ve uygulama dondurulmuş durumdan çıkarıldığında teslim edilir. Bu politika, çok fazla geri çağırma işlevi sıraya alınırsa arabellek taşmalarına veya eski etkinliklerin birikmesine yol açabileceğinden dikkatli olunmalıdır.
Aşağıdaki örnekte, dondurulmuş uygulamalara geri çağırma işlevleri bırakan bir RemoteCallbackList örneğinin nasıl oluşturulacağı ve kullanılacağı gösterilmektedir:
Java
RemoteCallbackList<IMyCallbackInterface> callbacks =
new RemoteCallbackList.Builder<IMyCallbackInterface>(
RemoteCallbackList.FROZEN_CALLEE_POLICY_DROP)
.setExecutor(myExecutor)
.build();
// Registering a callback:
callbacks.register(callback);
// Broadcasting to all registered callbacks:
callbacks.broadcast((callback) -> callback.onSomeEvent(eventData));
Kotlin
val callbacks =
RemoteCallbackList.Builder<IMyCallbackInterface>(
RemoteCallbackList.FROZEN_CALLEE_POLICY_DROP
)
.setExecutor(myExecutor)
.build()
// Registering a callback:
callbacks.register(callback)
// Broadcasting to all registered callbacks:
callbacks.broadcast { callback -> callback.onSomeEvent(eventData) }
FROZEN_CALLEE_POLICY_DROP kullanıyorsanız sistem, geri çağırmaya ev sahipliği yapan işlem dondurulmamışsa callback.onSomeEvent() öğesini çağırır.
Sistem hizmetleri ve uygulama etkileşimleri
Sistem hizmetleri genellikle bağlayıcıyı kullanarak birçok farklı uygulamayla etkileşim kurar. Uygulamalar önbelleğe alınmış ve dondurulmuş durumlara girebildiğinden, sistem hizmetlerinin sistem kararlılığını ve performansını korumak için bu etkileşimleri sorunsuz bir şekilde yönetmeye özen göstermesi gerekir.
Sistem hizmetlerinin, uygulama işlemlerinin çeşitli nedenlerle sonlandırıldığı durumları zaten işlemesi gerekir. Bu durumda, onlar adına çalışmayı durdurur ve ölü işlemlere geri aramalar sunmaya devam etmez. Uygulamaların dondurulması, mevcut izleme sorumluluğunun bir uzantısıdır.
Uygulama durumlarını sistem hizmetlerinden izleme
system_server içinde veya yerel arka plan programları olarak çalışan sistem hizmetleri de uygulama işlemlerinin önemini ve dondurulmuş durumunu izlemek için daha önce açıklanan API'leri kullanabilir:
ActivityManager.addOnUidImportanceListener: Sistem hizmetleri, UID önemindeki değişiklikleri izlemek için bir dinleyici kaydedebilir. Bir uygulamadan bağlayıcı çağrısı veya geri arama alındığında hizmet, UID'yi almak ve bunu dinleyici tarafından izlenen önem durumuyla ilişkilendirmek içinBinder.getCallingUid()'yi kullanabilir. Bu, sistem hizmetlerinin arama uygulamasının önbelleğe alınmış durumda olup olmadığını bilmesini sağlar.IBinder.addFrozenStateChangeCallback: Bir sistem hizmeti, bir uygulamadan bağlayıcı nesne aldığında (örneğin, geri çağırma kaydının bir parçası olarak) bu belirliIBinderörneğindeFrozenStateChangeCallbackkaydetmelidir. Bu, bağlayıcıyı barındıran uygulama işlemi dondurulduğunda veya dondurulması kaldırıldığında sistem hizmetini doğrudan bilgilendirir.
Sistem hizmetleri için öneriler
Uygulamalarla etkileşime girebilecek tüm sistem hizmetlerinin, iletişim kurdukları uygulama işlemlerinin önbelleğe alınmış ve dondurulmuş durumunu izlemesini öneririz. Bunu yapmamanız şu sonuçlara yol açabilir:
- Kaynak tüketimi: Önbelleğe alınmış ve kullanıcı tarafından görünür olmayan uygulamalar için işlem yapmak sistem kaynaklarının boşa harcanmasına neden olabilir.
- Uygulama kilitlenmeleri: Dondurulmuş uygulamalara yapılan senkron bağlayıcı çağrıları, uygulamaların kilitlenmesine neden olur. Dondurulmuş uygulamalara yapılan eşzamansız bağlayıcı çağrıları, eşzamansız işlem arabellekleri taşarsa kilitlenmeye neden olur.
- Beklenmeyen uygulama davranışı: Dondurulmuş uygulamalar, dondurulmuş durumdayken kendilerine gönderilen arabelleğe alınmış tüm eşzamansız bağlayıcı işlemlerini hemen alır. Uygulamalar dondurulmuş durumda süresiz kalabilir. Bu nedenle, arabelleğe alınmış işlemler çok eski olabilir.
Sistem hizmetleri genellikle uzak geri aramaları yönetmek ve ölü işlemleri otomatik olarak işlemek için RemoteCallbackList kullanır. Dondurulmuş uygulamaları işlemek için RemoteCallbackList'nın mevcut kullanımını genişletin. Bunun için Use RemoteCallbackList (RemoteCallbackList Kullanımı) bölümünde açıklandığı gibi dondurulmuş çağıran politikası uygulayın.