Android mimarisi için öneriler

Bu sayfada çeşitli mimari en iyi uygulamaları ve önerileri sunulmaktadır. Uygulamanızın kalitesini, sağlamlığını ve ölçeklenebilirliğini artırmak için bu uygulamaları benimseyin. Ayrıca uygulamanızın bakımını ve testini de 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 olan 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 ve doğru kaynak ilkesine uyar ve tek yönlü veri akışı ilkelerini izler. Katmanlı mimariyle ilgili en iyi uygulamalardan bazıları şunlardır:

Ö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 paket veya modüle yerleştirmeyi seçebilirsiniz.
Net bir şekilde tanımlanmış bir kullanıcı arayüzü katmanı kullanın. Kullanıcı arayüzü katmanı, uygulama verilerini ekranda gösterir ve kullanıcının etkileşim kurduğu birincil nokta olarak işlev görür. Jetpack Compose, uygulamanızın kullanıcı arayüzünü oluşturmak için önerilen modern araç setidir.
  • Küçük uygulamalarda, veri katmanı türlerini bir ui paket veya modüle 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şim kurduğu birincil nokta olarak hizmet vermektir. Kullanıcı arayüzü katmanıyla ilgili bazı en iyi uygulamalar:

Öneri Açıklama
Tek Yönlü Veri Akışı (UDF)'nı izleyin. Tek Yönlü Veri Akışı (UDF) ilkelerini uygulayın. Bu ilkelerde, ViewModel'ler 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şlemleri 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 ViewModel'i iş mantığı durumu bilgisi depolayıcısı olarak kullanma başlıklı makaleye bakın.

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 olan 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 bir durum güncellemesi gerçekleştirin. 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, kullanıcı arayüzü durumunun yaşam döngüsünden haberdar bir şekilde nasıl toplanacağı özetlenmektedir:

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

ViewModel

ViewModels, kullanıcı arayüzü durumunu sağlamak ve veri katmanına erişmekten sorumludur. ViewModel'lerle ilgili en iyi uygulamalardan bazıları şunlardır:

Ö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 iletilmemelidir. 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şimde bulunur:

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

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

  • Ekran düzeyinde composable'lar,
  • Görünümlerdeki Etkinlikler/Parçalar,
  • Jetpack Navigation kullanılırken hedefler veya grafikler.
Yeniden kullanılabilir kullanıcı arayüzü bileşenlerinde düz durum bilgisi depolayıcı 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 parçası 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üyle WhileSubscribed(5000) politikasını kullanarak uiState oluşturun. (Bu kod örneğine bakın.)
  • Veri katmanından gelen veri akışlarının olmadığı daha basit durumlarda MutableStateFlow olarak sunulan StateFlow 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ü

Activity yaşam döngüsü ile çalışmayla ilgili en iyi uygulamaları takip edin:

Ö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 simgesini 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 oluşturucu ekleme) kullanın.
Gerekirse bir bileşeni kapsam içine alı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 (ör. 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ş ViewModels'e sahip olmalıdır.

Test

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

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

Proje "hello world" uygulaması kadar basit olmadığı sürece test edin. En azından aşağıdakileri 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 kullanışlı olan kullanıcı arayüzü gezinme testleri
Sahteleri mock'lara tercih edin. Sahteleri kullanma hakkında daha fazla bilgi için Android'de test çiftlerini kullanma başlıklı makaleyi inceleyin.
Test StateFlows. StateFlow testini yaparken şunları yapın:

Daha fazla bilgi için Android'de ne test edilmeli? ve Compose düzeninizi test etme başlıklı makaleleri inceleyin.

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 bir 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ızı adlandırırken 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()).
Adlandırma özellikleri.
İ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ışını veya başka bir akışı kullanıma 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 önek olarak Default simgesini 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 önekini 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