Bu cevabı '09'da Android nispeten yeniyken yazdım ve Android geliştirmede pek sağlam olmayan alanlar vardı. Bu yazının altına uzun bir zeyilname ekledim, bazı eleştirileri ele aldım ve alt sınıflandırma uygulaması yerine Singletons kullanımıyla ilgili felsefi bir anlaşmazlığı detaylandırdım. Kendi sorumluluğunuzdadır okuyun.
ORİJİNAL CEVAP:
Karşılaştığınız daha genel sorun, çeşitli Faaliyetler ve uygulamanızın tüm bölümlerinde durumun nasıl kaydedileceğidir. Statik bir değişken (örneğin, bir singleton) bunu başarmanın yaygın bir Java yoludur. Bununla birlikte, Android'de daha zarif bir yolun, durumunuzu Uygulama bağlamıyla ilişkilendirmek olduğunu buldum.
Bildiğiniz gibi, her Etkinlik aynı zamanda en geniş anlamıyla yürütme ortamı hakkında bilgi olan bir Bağlamdır. Uygulamanızın bir bağlamı vardır ve Android, uygulamanızda tek bir örnek olarak var olacağını garanti eder.
Bunu yapmanın yolu, kendi android.app.Application alt sınıfınızı oluşturmak ve ardından bu sınıfı bildiriminizde uygulama etiketinde belirtmektir. Artık Android otomatik olarak bu sınıfın bir örneğini oluşturacak ve tüm uygulamanız için kullanılabilir hale getirecektir. Yöntemi context
kullanarak herhangi birinden erişebilirsiniz Context.getApplicationContext()
( aynı etkiye sahip Activity
bir yöntem de sağlar getApplication()
). Takip edilecek uyarılar ile son derece basitleştirilmiş bir örnek aşağıdadır:
class MyApp extends Application {
private String myState;
public String getState(){
return myState;
}
public void setState(String s){
myState = s;
}
}
class Blah extends Activity {
@Override
public void onCreate(Bundle b){
...
MyApp appState = ((MyApp)getApplicationContext());
String state = appState.getState();
...
}
}
Bu, esasen statik bir değişken veya singleton kullanmakla aynı etkiye sahiptir, ancak mevcut Android çerçevesine oldukça iyi entegre olur. Bunun işlemler arasında çalışmayacağını unutmayın (uygulamanız birden çok işlemi olan nadir uygulamalardan biri olması durumunda).
Yukarıdaki örnekten not edilecek bir şey; bunun yerine şöyle bir şey yaptığımızı varsayalım:
class MyApp extends Application {
private String myState = /* complicated and slow initialization */;
public String getState(){
return myState;
}
}
Şimdi bu yavaş başlatma (disk vurmak, ağ vurmak, herhangi bir engelleme, vb gibi) Uygulama her başlatıldığında yapılacaktır! Bunun süreç için sadece bir kez olduğunu düşünebilirsiniz ve maliyeti yine de ödemek zorundayım, değil mi? Örneğin, Dianne Hackborn'un aşağıda belirttiği gibi, işleminizin bir arka plan yayın olayını işlemesi için -sadece- somutlaştırılması tamamen mümkündür. Yayın işleminizin bu duruma ihtiyacı yoksa, hiçbir şey için potansiyel olarak bir dizi karmaşık ve yavaş işlem gerçekleştirmişsinizdir. Tembel örnekleme burada oyunun adıdır. Aşağıdakiler, en basit kullanımlardan başka bir şey için daha mantıklı olan Uygulamayı kullanmanın biraz daha karmaşık bir yoludur:
class MyApp extends Application {
private MyStateManager myStateManager = new MyStateManager();
public MyStateManager getStateManager(){
return myStateManager ;
}
}
class MyStateManager {
MyStateManager() {
/* this should be fast */
}
String getState() {
/* if necessary, perform blocking calls here */
/* make sure to deal with any multithreading/synchronicity issues */
...
return state;
}
}
class Blah extends Activity {
@Override
public void onCreate(Bundle b){
...
MyStateManager stateManager = ((MyApp)getApplicationContext()).getStateManager();
String state = stateManager.getState();
...
}
}
Application subclassing'i burada daha zarif bir çözüm olarak singletons kullanmaya tercih etsem de, geliştiricilerin durumun Application subclass ile ilişkilendirilmesinin performansı ve çok iş parçacıklı etkileri aracılığıyla hiç düşünmemek yerine gerçekten singletonları tercih ediyorum.
Not 1: Ayrıca, anti-cafe yorum gibi, uygulama geçersiz kılma uygulamanıza doğru bağlamak için bildirim dosyasında bir etiket gereklidir. Daha fazla bilgi için yine Android belgelerine bakın. Bir örnek:
<application
android:name="my.application.MyApp"
android:icon="..."
android:label="...">
</application>
NOT 2: user608578, bunun yerel nesne yaşam döngülerini yönetmekle nasıl çalıştığını sorar. Android ile yerel kodu en ufak bir şekilde kullanma hızına sahip değilim ve bunun çözümümle nasıl etkileşime gireceğini cevaplamak için nitelikli değilim. Birisinin buna bir cevabı varsa, ben onları kredilendirmek ve maksimum görünürlük için bu yazıya bilgi koymak istiyorum.
EK:
Bazı insanların belirttiği gibi, bu kalıcı bir durum için bir çözüm değildir , belki de orijinal cevapta daha fazla vurgulamam gerekirdi. Yani bu, uygulama ömürleri boyunca kalıcı olması gereken kullanıcı veya diğer bilgileri kaydetmek için bir çözüm değildir. Bu nedenle, diske kalıcı olarak ihtiyaç duyulan herhangi bir şeyin bir Uygulama alt sınıfı aracılığıyla saklanmaması gerektiğinden, herhangi bir zamanda öldürülen Uygulamalara, vb. Geçici, kolayca yeniden oluşturulabilir uygulama durumunu (örneğin bir kullanıcının oturum açıp açmadığını) ve tek örnekli bileşenleri (örneğin uygulama ağ yöneticisi) ( NOT singleton!) Saklamak için bir çözümdür .
Dayerman, Reto Meier ve Dianne Hackborn ile Uygulama alt sınıflarının kullanımının Singleton kalıpları lehine cesaret kırıldığı ilginç bir sohbete işaret edecek kadar nazikti . Somatik, daha önce bu doğaya ait bir şeyi daha önce işaret etmişti, ancak o zaman görmedim. Reto ve Dianne'nin Android platformunu sürdürmedeki rolleri nedeniyle, tavsiyelerini görmezden gelmeyi tavsiye edemiyorum. Dedikleri şey gider. Singleton'u Uygulama alt sınıflarına tercih etme konusunda dile getirilen görüşlere katılmıyorum. Anlaşmamda, Singleton tasarım modelinin StackExchange açıklamasında en iyi açıklanan kavramlardan yararlanacağım, böylece bu cevaptaki terimleri tanımlamak zorunda değilim. Devam etmeden önce bağlantıyı gözden geçirmenizi şiddetle tavsiye ediyorum. Noktadan noktaya:
Dianne, "Uygulamadan alt sınıflamak için hiçbir neden yoktur. Tek birton yapmaktan farklı değildir ..." Bu ilk iddia yanlıştır. Bunun iki ana nedeni var. 1) Uygulama sınıfı, bir uygulama geliştiricisi için daha iyi bir ömür boyu garanti sağlar; uygulamanın kullanım ömrü garantilidir. Bir singleton, etkili bir şekilde olmasına rağmen, uygulamanın kullanım ömrüne özel olarak bağlı değildir. Bu, ortalama uygulama geliştiriciniz için bir sorun olmayabilir, ancak bunun tam olarak Android API'nin sunması gereken sözleşme türü olduğunu ve ilgili kullanım ömrünü en aza indirerek Android sistemine daha fazla esneklik sağladığını iddia ediyorum. veri. 2) Application sınıfı, uygulama geliştiricisine durum için tek bir örnek tutucu sağlar, ki bu Singleton devlet sahibinden çok farklı. Farklılıkların listesi için yukarıdaki Singleton açıklama bağlantısına bakın.
Dianne, "... Uygulama nesnenizin bağımsız uygulama mantığı ne olması gerektiğine dair bu büyük karışıklık haline geldiğini gördüğünüzde gelecekte pişman olacağınız bir şey olacak." Bu kesinlikle yanlış değildir, ancak bu uygulama üzerinden Singleton'u seçmenin bir nedeni değildir. Diane'in argümanlarından hiçbiri, Singleton kullanmanın bir Uygulama alt sınıfından daha iyi bir neden sunmadığını, kurmaya çalıştığı tek şey, Singleton kullanmanın yanlış olduğuna inandığım bir Uygulama alt sınıfından daha kötü olmadığıdır.
"Ve bu, doğal olarak bu şeyleri nasıl yönetmeniz gerektiğine - talep üzerine onları başlatmaya" yol açar. Bu, bir Uygulama alt sınıfını kullanarak da istek üzerine başlatamamanız için hiçbir neden olmadığı gerçeğini göz ardı eder. Yine hiçbir fark yok.
Dianne ile biten "Çerçevenin kendisi yüklü kaynakların önbellekleri, nesne havuzları, vb gibi uygulama için tuttuğu tüm küçük paylaşılan veriler için ton ve ton tek ton vardır. Harika çalışıyor." Singletons kullanmanın iyi çalışamayacağını veya meşru bir alternatif olmadığını iddia etmiyorum. Singletons'un Android sistemiyle bir Uygulama alt sınıfı kullanmak kadar güçlü bir sözleşme sağlamadığını ve ayrıca Singletons kullanmanın genellikle kolayca değiştirilemeyen ve yolda birçok soruna yol açan esnek olmayan bir tasarıma işaret ettiğini iddia ediyorum. Android API'nın geliştirici uygulamalarına sunduğu güçlü sözleşme IMHO, Android ile programlamanın en çekici ve hoş yönlerinden biridir ve Android platformunu bugünkü başarıya taşıyan erken geliştiricinin benimsenmesine yardımcı oldu.
Dianne, Uygulama alt sınıflarını kullanmanın ek bir dezavantajından da bahseterek aşağıda yorum yaptı, daha az performans kodu yazmayı teşvik edebilir veya kolaylaştırabilir. Bu çok doğrudur ve burada mükemmelliği düşünmenin ve Uygulama alt sınıfını kullanıyorsanız doğru yaklaşımı almanın önemini vurgulamak için bu cevabı düzenledim. Dianne'nin belirttiği gibi, işlem yalnızca bir arka plan yayını için yükleniyor olsa bile, işleminiz her yüklendiğinde (uygulamanız birden çok işlemde çalışıyorsa bir kerede birden çok kez olabilir!) Uygulama sınıfınızın somutlaştırılacağını hatırlamanız önemlidir. Etkinlik. Bu nedenle, Uygulama sınıfını, herhangi bir işleme tabi tutulması yerine uygulamanızın paylaşılan bileşenlerine işaretçiler için bir havuz olarak kullanmak daha önemlidir!
Daha önceki StackExchange bağlantısından çalındığı gibi, sizi Singletons için aşağıdaki dezavantajlar listesine bırakıyorum:
- Soyut veya arayüz sınıflarını kullanamama;
- Alt sınıfta yetersizlik;
- Uygulama boyunca yüksek kuplaj (değiştirilmesi zor);
- Test edilmesi zor (birim testlerinde sahte / alay edilemez);
- Değişebilir durumda paralelleme zor (kapsamlı kilitleme gerektirir);
ve kendiminkini ekle:
- Android (veya diğer birçok) geliştirme için uygun olmayan belirsiz ve yönetilemez ömür boyu sözleşme;