Android mimarisi için öneriler

Bu sayfada, Mimari ile ilgili çeşitli en iyi uygulamalar ve öneriler sunulmaktadır. Uygulamanızın kalitesini, sağlamlığını ve ölçeklenebilirliğini artırmak için bunları kullanın. Ayrıca, uygulamanızı sürdürmeyi ve test etmeyi kolaylaştırır.

Aşağıdaki en iyi uygulamalar konularına göre gruplandırılmıştır. Her birinin, önerinin ne kadar etkili olduğunu yansıtan bir önceliği vardır. Öncelik listesi aşağıdaki gibidir:

  • Kesinlikle önerilir: Bu uygulamayı, yaklaşımınızla temelden çelişmediği sürece uygulayın.
  • Önerilir: Bu uygulama, uygulamanızı iyileştirme olasılığı yüksek bir uygulamadır.
  • İsteğe bağlı: Bu uygulama, belirli durumlarda uygulamanızı iyileştirebilir.

Katmanlı mimari

Önerdiğimiz katmanlı mimari, sorumlulukların ayrılmasını destekler. Veri modellerinden kullanıcı arayüzü oluşturur, tek doğruluk kaynağı ilkesine uyar ve tek yönlü veri akışı ilkelerini izler. Katmanlı mimariyle ilgili bazı en iyi uygulamalar:

Öneri Açıklama
Net bir şekilde tanımlanmış bir veri katmanı kullanın. Veri katmanı, uygulama verilerini uygulamanın geri kalanına sunar ve uygulamanızın iş mantığının büyük bir bölümünü içerir.
  • Yalnızca tek bir veri kaynağı içerseler bile depolar oluşturun.
  • Küçük uygulamalarda, veri katmanı türlerini bir data paketine veya modülüne yerleştirmeyi seçebilirsiniz.
Net bir şekilde tanımlanmış kullanıcı arayüzü katmanı kullanın. Kullanıcı arayüzü katmanı, uygulama verilerini ekranda gösterir ve kullanıcı etkileşiminin birincil noktası olarak işlev görür. Uygulamanızın kullanıcı arayüzünü oluşturmak için önerilen modern araç seti Jetpack Compose'dur.
  • Küçük uygulamalarda, veri katmanı türlerini bir ui paketine veya modülüne yerleştirmeyi seçebilirsiniz.
Kullanıcı arayüzü katmanıyla ilgili en iyi uygulamalar hakkında daha fazla bilgi için Kullanıcı arayüzü katmanı başlıklı makaleyi inceleyin.
Bir depo kullanarak veri katmanındaki uygulama verilerini kullanıma sunun.

Kullanıcı arayüzü katmanındaki composable'lar veya ViewModel'ler gibi bileşenlerin bir veri kaynağıyla doğrudan etkileşimde bulunmadığından emin olun. Veri kaynaklarına örnekler:

  • Veritabanları, DataStore, SharedPreferences, Firebase API'leri.
  • GPS konum sağlayıcıları.
  • Bluetooth veri sağlayıcıları.
  • Ağ bağlantısı durumu sağlayıcıları.
Coroutine'ları ve akışları kullanın. Katmanlar arasında iletişim kurmak için coroutines ve flow'ları kullanın.

Coroutine'lerle ilgili en iyi uygulamalar hakkında daha fazla bilgi için Android'de coroutine'lerle ilgili en iyi uygulamalar başlıklı makaleyi inceleyin.

Alan katmanı kullanın. Birden fazla ViewModel'de veri katmanıyla etkileşimde bulunan iş mantığını yeniden kullanmanız gerekiyorsa veya belirli bir ViewModel'in iş mantığı karmaşıklığını basitleştirmek istiyorsanız kullanım alanlarıyla birlikte bir alan katmanı kullanın.

Kullanıcı arayüzü katmanı

Kullanıcı arayüzü katmanının rolü, uygulama verilerini ekranda göstermek ve kullanıcının etkileşimde bulunduğu birincil nokta olarak hizmet vermektir. Kullanıcı arayüzü katmanıyla ilgili bazı en iyi uygulamaları aşağıda bulabilirsiniz:

Öneri Açıklama
Tek Yönlü Veri Akışı (UDF)'nı izleyin. Tek Yönlü Veri Akışı (UDF) ilkelerini uygulayın. Bu ilkelerde, ViewModels, gözlemci kalıbını kullanarak kullanıcı arayüzü durumunu gösterir ve yöntem çağrıları aracılığıyla kullanıcı arayüzünden işlemler alır.
Avantajları uygulamanız için geçerliyse AAC ViewModels'i kullanın. İş mantığını işlemek ve kullanıcı arayüzü durumunu kullanıcı arayüzüne göstermek için uygulama verilerini getirmek üzere AAC ViewModels'i kullanın.

ViewModel en iyi uygulamaları hakkında daha fazla bilgi için Mimari önerileri başlıklı makaleyi inceleyin.

ViewModel'lerin avantajları hakkında daha fazla bilgi için The ViewModel as a business logic state holder (ViewModel'i iş mantığı durum bilgisi depolayıcısı olarak kullanma) başlıklı makaleyi inceleyin.

Yaşam döngüsüne duyarlı kullanıcı arayüzü durumu toplama özelliğini kullanın. Uygun yaşam döngüsü farkında eş yordam oluşturucuyu (collectAsStateWithLifecycle) kullanarak kullanıcı arayüzünden kullanıcı arayüzü durumunu toplayın.

collectAsStateWithLifecycle hakkında daha fazla bilgi edinin.

ViewModel'den kullanıcı arayüzüne etkinlik göndermeyin. Etkinliği ViewModel'de hemen işleyin ve etkinliğin işlenmesi sonucunda durum güncellemesi yapın. Kullanıcı arayüzü etkinlikleri hakkında daha fazla bilgi için ViewModel etkinliklerini işleme başlıklı makaleyi inceleyin.
Tek etkinlikli bir uygulama kullanın. Uygulamanızda birden fazla ekran varsa ekranlar arasında gezinmek ve uygulamanıza derin bağlantı oluşturmak için Navigation 3'ü kullanın.
Jetpack Compose'u kullanın. Telefonlar, tabletler, katlanabilir cihazlar ve Wear OS için yeni uygulamalar oluşturmak üzere Jetpack Compose'u kullanın.

Aşağıdaki snippet'te, yaşam döngüsünden haberdar bir şekilde kullanıcı arayüzü durumunun nasıl toplanacağı özetlenmektedir:

  @Composable
  fun MyScreen(
      viewModel: MyViewModel = viewModel()
  ) {
      val uiState by viewModel.uiState.collectAsStateWithLifecycle()
  }

ViewModel

ViewModels, kullanıcı arayüzü durumunu sağlamaktan ve veri katmanına erişmekten sorumludur. ViewModel'lerle ilgili bazı en iyi uygulamaları aşağıda bulabilirsiniz:

Öneri Açıklama
ViewModel'leri Android yaşam döngüsünden bağımsız tutun. ViewModel'lerde yaşam döngüsüyle ilgili herhangi bir türe referans tutmayın. Activity, Context veya Resources'ı bağımlılık olarak iletmeyin. ViewModel'de bir Context gerekiyorsa bunun doğru katmanda olup olmadığını dikkatlice değerlendirin.
Coroutine'ları ve akışları kullanın.

ViewModel, aşağıdaki öğeleri kullanarak veri veya alan katmanlarıyla etkileşim kurar:

  • Uygulama verilerini almak için Kotlin akışları
  • viewModelScope kullanarak işlem gerçekleştirmek için suspend işlevleri
ViewModel'ları ekran düzeyinde kullanın.

Yeniden kullanılabilir kullanıcı arayüzü parçalarında ViewModel'leri kullanmayın. ViewModel'leri şu durumlarda kullanmalısınız:

Daha karmaşık veya duruma göre dinamik davranışa sahip composable'lar için, ViewModel'i doğrudan composable'ın çağrı sitesine kapsamlandırmak üzere rememberViewModelStoreOwner() kullanın.

Yeniden kullanılabilir kullanıcı arayüzü bileşenlerinde basit durum tutucu sınıflar kullanın. Yeniden kullanılabilir kullanıcı arayüzü bileşenlerindeki karmaşıklığı işlemek için basit durum bilgisi depolayıcı sınıfları kullanın. Bunu yaptığınızda durum yükseltilebilir ve harici olarak kontrol edilebilir.
AndroidViewModel kullanmayın. AndroidViewModel değil, ViewModel sınıfını kullanın. ViewModel'de Application sınıfını kullanmayın. Bunun yerine bağımlılığı kullanıcı arayüzüne veya veri katmanına taşıyın.
Bir kullanıcı arayüzü durumunu kullanıma sunma. ViewModel'lerinizin, verileri uiState adlı tek bir özellik aracılığıyla kullanıcı arayüzüne sunmasını sağlayın. Kullanıcı arayüzünde birden fazla alakasız veri gösteriliyorsa VM, birden fazla kullanıcı arayüzü durumu özelliği gösterebilir.
  • uiState öğesini StateFlow yapın.
  • Veriler hiyerarşinin diğer katmanlarından veri akışı olarak geliyorsa stateIn operatörünü WhileSubscribed(5000) politikasıyla birlikte kullanarak uiState oluşturun. (Bu kod örneğine bakın.)
  • Veri katmanından gelen veri akışlarının olmadığı daha basit durumlarda, değişmez bir StateFlow olarak sunulan bir MutableStateFlow kullanmak kabul edilebilir.
  • ${Screen}UiState öğesini veri, hata ve yükleme sinyalleri içerebilen bir veri sınıfı olarak kullanmayı seçebilirsiniz. Farklı durumlar özel ise bu sınıf kapalı sınıf da olabilir.

Aşağıdaki snippet'te, ViewModel'den kullanıcı arayüzü durumunun nasıl kullanıma sunulacağı özetlenmektedir:

@HiltViewModel
class BookmarksViewModel @Inject constructor(
    newsRepository: NewsRepository
) : ViewModel() {

    val feedState: StateFlow<NewsFeedUiState> =
        newsRepository
            .getNewsResourcesStream()
            .mapToFeedState(savedNewsResourcesState)
            .stateIn(
                scope = viewModelScope,
                started = SharingStarted.WhileSubscribed(5_000),
                initialValue = NewsFeedUiState.Loading
            )

    // ...
}

Yaşam döngüsü

Etkinlik yaşam döngüsüyle çalışmayla ilgili en iyi uygulamalardan yararlanın:

Öneri Açıklama
Activity yaşam döngüsü geri çağırmalarını geçersiz kılmak yerine composable'larda yaşam döngüsüne duyarlı efektler kullanın.

Kullanıcı arayüzüyle ilgili görevleri çalıştırmak için Activity yaşam döngüsü yöntemlerini (ör. onResume) geçersiz kılmayın. Bunun yerine Compose'un LifecycleEffects veya yaşam döngüsüne duyarlı coroutine kapsamlarını kullanın:

  • Etkinliğiniz başladığında ve durduğunda eşzamanlı çalışma yapmak için LifecycleStartEffect kullanın.
  • Etkinliğiniz devam ettiğinde ve duraklatıldığında eşzamanlı çalışma yapmak için LifecycleResumeEffect kullanın.
  • Yaşam döngüsü etkinliklerine yanıt olarak eşzamansız işlemler gerçekleştirmek için repeatOnLifecycle kullanın.
  • collectAsStateWithLifecycle kullanarak akışlardan eşzamansız veriler toplama.

Aşağıdaki snippet'te, belirli bir yaşam döngüsü durumu verildiğinde işlemlerin nasıl gerçekleştirileceği özetlenmektedir:

  @Composable
  fun LocationChangedEffect(
    locationManager: LocationManager,
    onLocationChanged: (Location) -> Unit
  ) {
    val currentOnLocationChanged by rememberUpdatedState(onLocationChanged)

    LifecycleStartEffect(locationManager) {
        val listener = LocationListener { newLocation ->
            currentOnLocationChanged(newLocation)
        }

        try {
            locationManager.requestLocationUpdates(
                LocationManager.GPS_PROVIDER,
                1000L,
                1f,
                listener,
            )
        } catch (e: SecurityException) {
            // TODO: Handle missing permissions
        }

        onStopOrDispose {
            locationManager.removeUpdates(listener)
        }
    }
  }

Bağımlılıkları yönetme

Bileşenler arasındaki bağımlılıkları yönetirken en iyi uygulamaları takip edin:

Öneri Açıklama
Bağımlılık ekleme özelliğini kullanın. Mümkün olduğunda bağımlılık ekleme en iyi uygulamalarını, özellikle de oluşturucu ekleme'yi kullanın.
Gerekirse kapsamı bir bileşenle sınırlayın. Tür, paylaşılması gereken değiştirilebilir veriler içerdiğinde veya türün başlatılması maliyetli olduğunda ve uygulamada yaygın olarak kullanıldığında kapsamı bir bağımlılık kapsayıcısı ile sınırlayın.
Hilt'i kullanın. Basit uygulamalarda Hilt veya manuel bağımlılık ekleme'yi kullanın. Projeniz yeterince karmaşıksa (örneğin, aşağıdakilerden herhangi birini içeriyorsa) Hilt'i kullanın:
  • ViewModel'lerin kullanıldığı birden fazla ekran
  • WorkManager kullanma
  • Gezinme geri yığınına göre kapsamı belirlenmiş ViewModel'ler içerir.

Test

Test ile ilgili bazı en iyi uygulamaları aşağıda bulabilirsiniz:

Öneri Açıklama
Neyi test edeceğinizi bilin.

Proje "hello world" uygulaması kadar basit olmadığı sürece test edin. En azından şunları ekleyin:

  • Akışlar dahil ViewModel'ler için birim testleri
  • Veri katmanı öğeleri (ör. depolar ve veri kaynakları) için birim testleri
  • CI'da regresyon testleri olarak faydalı olan kullanıcı arayüzü gezinme testleri
  • Uygulama başlatma ve kullanıcı arayüzü oluşturmayı ölçmek için Macrobenchmark'ı kullanan performans testleri
Mock'lar yerine sahteleri tercih edin. Sahte verileri kullanma hakkında daha fazla bilgi için Android'de test çiftlerini kullanma başlıklı makaleyi inceleyin.
StateFlow'ları test edin. StateFlow test ederken aşağıdakileri yapın:

Daha fazla bilgi için Android'de test edilecek öğeler ve Compose düzeninizi test etme başlıklı makaleleri inceleyin.

Performans

Aşağıda, performansı artırmaya yönelik bazı en iyi uygulamalar verilmiştir:

Öneri Açıklama
Uygulamanızı küçültmek ve optimize etmek için R8'i kullanın. Kullanılmayan kodu kaldırmak, sınıfları karartmak ve çalışma zamanı performansını artırmak için kodu yeniden yazmak üzere derleme yapılandırmanızda R8'i etkinleştirin.
Temel Profilleri ve Başlangıç Profillerini uygulayın. Kritik kod yollarını önceden derlemek için Baseline Profiles (Temel Profil) ve Startup Profiles (Başlangıç Profili) oluşturun. Bu sayede başlatma gecikmesi (TTID ve TTFD) önemli ölçüde azalır ve jank ile ANR'ler en aza indirilir.
Macrobenchmark ile performansı test edin. Uygulamanızın performansını test etmek ve gerilemeleri önlemek için Macrobenchmark kitaplığını kullanın.

Modeller

Uygulamalarınızda model geliştirirken aşağıdaki en iyi uygulamalara uyun:

Öneri Açıklama
Karmaşık uygulamalarda her katman için bir model oluşturun.

Karmaşık uygulamalarda, mantıklı olduğunda farklı katmanlarda veya bileşenlerde yeni modeller oluşturun. Aşağıdaki örnekleri inceleyin:

  • Uzak veri kaynağı, ağ üzerinden aldığı modeli yalnızca uygulamanın ihtiyaç duyduğu verileri içeren daha basit bir sınıfa eşleyebilir.
  • Depolar, DAO modellerini yalnızca kullanıcı arayüzü katmanının ihtiyaç duyduğu bilgileri içeren daha basit veri sınıflarıyla eşleyebilir.
  • ViewModel, UiState sınıflarında veri katmanı modellerini içerebilir.

Adlandırma kuralları

Kod tabanınıza ad verirken aşağıdaki en iyi uygulamalara dikkat etmeniz gerekir:

Öneri Açıklama
Adlandırma yöntemleri.
İsteğe bağlı
Yöntemleri adlandırmak için fiil ifadeleri kullanın (ör. makePayment()).
Özellikleri adlandırma
İsteğe bağlı
Özellikleri adlandırırken isim öbekleri kullanın (ör. inProgressTopicSelection).
Veri akışlarını adlandırma.
İsteğe bağlı
Bir sınıf, Flow akışı veya başka bir akış sunduğunda adlandırma kuralı get{model}Stream olur. Örneğin, getAuthorStream(): Flow<Author>. İşlev bir model listesi döndürüyorsa modelin çoğul adını kullanın: getAuthorsStream(): Flow<List<Author>>.
Arayüz uygulamalarını adlandırma.
İsteğe bağlı
Arayüz uygulamaları için anlamlı adlar kullanın. Daha iyi bir ad bulunamıyorsa ön ek olarak Default kullanın. Örneğin, NewsRepository arayüzü için OfflineFirstNewsRepository veya InMemoryNewsRepository olabilir. İyi bir ad bulamıyorsanız DefaultNewsRepository kullanın. Sahte uygulamaların önüne Fake ekleyin (ör. FakeAuthorsRepository).

Ek kaynaklar

Android mimarisi hakkında daha fazla bilgi için aşağıdaki ek kaynaklara bakın:

Belgeler

İçeriği görüntüleme