Android mimarisi için öneriler

Bu sayfada çeşitli mimari en iyi uygulamaları ve önerileri sunulmaktadır. Uygulamanızın kalitesini, dayanıklılığını ve ölçeklenebilirliğini iyileştirmek için bu özellikleri kullanın. Ayrıca, uygulamanızın bakımını ve test etmenizi de kolaylaştırırlar.

Aşağıdaki en iyi uygulamalar konuya göre gruplandırılmıştır. Her birinin, ekibin önerme derecesini yansıtan bir önceliği vardır. Öncelik listesi şu şekildedir:

  • Önerilir: Yaklaşımınızla temelde çelişmediği sürece bu uygulamayı kullanmalısınız.
  • Önerilir: Bu uygulama, uygulamanızı iyileştirmeye yardımcı olabilir.
  • İsteğe bağlı: Bu yöntemle uygulamanızı belirli durumlarda iyileştirebilirsiniz.

Katmanlı mimari

Önerdiğimiz katmanlı mimari, endişelerin ayrılmasını destekler. Kullanıcı arayüzünü veri modellerinden alır, tek doğru kaynak ilkesine uyar ve tek yönlü veri akışı ilkelerine uyar. Katmanlı mimari için bazı en iyi uygulamalar:

Öneri Açıklama
Açıkça tanımlanmış bir veri katmanı kullanın. Veri katmanı, uygulama verilerini uygulamanın geri kalanına gösterir ve uygulamanızın iş mantığının büyük bir kısmını içerir.
  • Yalnızca tek bir veri kaynağı içerse bile veri havuzları oluşturmanız gerekir.
  • Küçük uygulamalarda veri katmanı türlerini bir data paketine veya modülüne yerleştirmeyi seçebilirsiniz.
Açıkça tanımlanmış bir 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.
  • Küçük uygulamalarda veri katmanı türlerini bir ui paketine veya modülüne yerleştirmeyi seçebilirsiniz.
Diğer kullanıcı arayüzü katmanı en iyi uygulamalarını burada bulabilirsiniz.
Veri katmanı, bir depoyu kullanarak uygulama verilerini göstermelidir.

Kullanıcı arayüzü katmanındaki bileşenler (ör. derlenebilirler, etkinlikler veya ViewModel'ler) doğrudan bir veri kaynağıyla etkileşime girmemelidir. 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ı.
Eş yordamları ve akışları kullanın. Katmanlar arasında iletişim kurmak için coroutine'leri ve akışları kullanın.

Diğer coroutine en iyi uygulamalarına buradan ulaşabilirsiniz.

Alan katmanı kullanın. Birden fazla ViewModel'de veri katmanıyla etkileşime geçen iş mantığını yeniden kullanmanız veya belirli bir ViewModel'in iş mantığı karmaşıklığını basitleştirmeniz gerekiyorsa alan katmanı, kullanım alanları kullanın

kullanıcı arayüzü katmanı

Kullanıcı arayüzü katmanının rolü, uygulama verilerini ekranda görüntülemek ve kullanıcı etkileşiminin birincil noktası olarak hizmet etmektir. Kullanıcı arayüzü katmanına dair en iyi uygulamalardan bazıları şunlardır:

Öneri Açıklama
Tek Yönlü Veri Akışı (UDF)'nı uygulayın. ViewModel'lerin gözlemci kalıbını kullanarak kullanıcı arayüzü durumunu gösterdiği ve yöntem çağrıları aracılığıyla kullanıcı arayüzünden işlem aldığı Tek Yönlü Veri Akış (UDF) ilkelerine uyun.
Avantajları uygulamanız için geçerliyse AAC ViewModel'lerini kullanın. İş mantığını yönetmek için AAC ViewModel'lerini kullanın ve kullanıcı arayüzü durumunu kullanıcı arayüzüne (Compose veya Android Görünümler) göstermek için uygulama verilerini alın.

ViewModel en iyi uygulamalarına buradan göz atabilirsiniz.

ViewModel'lerin avantajlarını buradan inceleyebilirsiniz.

Yaşam döngüsüne duyarlı kullanıcı arayüzü durumu koleksiyonunu kullanın. Yaşam döngüsü bilincine sahip uygun coroutine oluşturucuyu kullanarak kullanıcı arayüzünden kullanıcı arayüzü durumunu toplayın: Görünüm sisteminde repeatOnLifecycle ve Jetpack Compose'da collectAsStateWithLifecycle.

repeatOnLifecycle hakkında daha fazla bilgi edinin.

collectAsStateWithLifecycle hakkında daha fazla bilgi edinin.

ViewModel'den kullanıcı arayüzüne etkinlik göndermeyin. Etkinliği ViewModel'de hemen işleme ve etkinliğin işlenmesinin sonucunda bir durum güncellemesine neden olma. Kullanıcı arayüzü etkinlikleri hakkında daha fazla bilgiyi burada bulabilirsiniz.
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 gezinme parçalarını veya gezinme oluşturma aracını 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üne duyarlı bir şekilde nasıl toplanacağı açıklanmaktadır:

Görüntüleme sayısı

class MyFragment : Fragment() {

    private val viewModel: MyViewModel by viewModel()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        viewLifecycleOwner.lifecycleScope.launch {
            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.uiState.collect {
                    // Process item
                }
            }
        }
    }
}

Oluştur

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

ViewModel

ViewModel'ler, kullanıcı arayüzü durumunu sağlamak ve veri katmanına erişim sağlamaktan sorumludur. ViewModel'ler için bazı en iyi uygulamalar:

Öneri Açıklama
ViewModel'ler Android yaşam döngüsüne bağlı olmamalıdır. ViewModel'ler, yaşam döngüsüyle ilgili herhangi bir türe referans içermemelidir. Bağımlılık olarak Activity, Fragment, Context veya Resources iletmeyin. ViewModel'de bir öğe için Context özelliği gerekiyorsa bunun doğru katmanda olup olmadığını kesinlikle değerlendirmeniz gerekir.
Eş yordamları ve akışları kullanın.

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

  • Uygulama verilerini almak için Kotlin akışları,
  • suspend, viewModelScope'i kullanarak işlem yapmak için işlevler sağlar.
ViewModel'leri ekran düzeyinde kullanın.

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

  • Ekran düzeyinde composable'lar
  • Görüntülemelerdeki Etkinlikler/Fragment'ler,
  • Jetpack Navigasyon'u kullanırken hedefler veya grafikler.
Yeniden kullanılabilir kullanıcı arayüzü bileşenlerinde düz durum tutucu sınıfları kullanın. Yeniden kullanılabilir kullanıcı arayüzü bileşenlerindeki karmaşıklığı yönetmek için basit durum tutucu sınıfları kullanın. Bu sayede durum harici olarak kaldırılabilir ve kontrol edilebilir.
AndroidViewModel kullanmayın. AndroidViewModel yerine ViewModel sınıfını kullanın. Application sınıfı ViewModel'de kullanılmamalıdır. Bunun yerine bağımlılığı kullanıcı arayüzüne veya veri katmanına taşıyın.
Kullanıcı arayüzü durumunu gösterme. Veri modelleri, verileri uiState adlı tek bir mülk aracılığıyla kullanıcı arayüzüne sunmalıdır. Kullanıcı arayüzünde birden fazla, birbiriyle alakalı olmayan veri gösteriliyorsa sanal makine birden fazla kullanıcı arayüzü durum özelliğini gösterebilir.
  • uiState için bir StateFlow oluşturmanız gerekir.
  • Veriler hiyerarşinin diğer katmanlarından gelen bir veri akışı olarak geliyorsa uiState'yi WhileSubscribed(5000) politikasıyla birlikte stateIn operatörünü kullanarak (örnek) oluşturmanız gerekir.
  • Veri katmanından gelen veri akışının olmadığı daha basit durumlarda, sabit StateFlow (örnek) olarak gösterilen MutableStateFlow kullanılabilir.
  • ${Screen}UiState değerini veri, hata ve yükleme sinyalleri içerebilecek bir veri sınıfı olarak ayarlayabilirsiniz. Farklı durumlar birbirinden hariçse bu sınıf mühürlü bir sınıf da olabilir.

Aşağıdaki snippet'te, kullanıcı arayüzü durumunun bir ViewModel'den nasıl gösterileceği özetlenmiştir:

@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ü

Android yaşam döngüsü ile çalışmayla ilgili bazı en iyi uygulamalar aşağıda verilmiştir:

Öneri Açıklama
Etkinlikler veya Parçalar'daki yaşam döngüsü yöntemlerini geçersiz kılmayın. Aktiviteler veya Fragment'lerde onResume gibi yaşam döngüsü yöntemlerini geçersiz kılmayın. Bunun yerine LifecycleObserver kullanın. Yaşam döngüsü belirli bir Lifecycle.State değerine ulaştığında uygulamanın işlem yapması gerekiyorsa repeatOnLifecycle API'sini kullanın.

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

Görüntüleme sayısı

class MyFragment: Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        viewLifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
            override fun onResume(owner: LifecycleOwner) {
                // ...
            }
            override fun onPause(owner: LifecycleOwner) {
                // ...
            }
        }
    }
}

Oluştur

@Composable
fun MyApp() {

    val lifecycleOwner = LocalLifecycleOwner.current
    DisposableEffect(lifecycleOwner, ...) {
        val lifecycleObserver = object : DefaultLifecycleObserver {
            override fun onStop(owner: LifecycleOwner) {
                // ...
            }
        }

        lifecycleOwner.lifecycle.addObserver(lifecycleObserver)
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(lifecycleObserver)
        }
    }
}

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

Bileşenler arasındaki bağımlılıkları yönetirken dikkate almanız gereken birkaç en iyi uygulama vardır:

Ö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 yapıcı eklemeyi kullanın.
Gerekirse bir bileşenin kapsamını belirleyin. Tür, paylaşılması gereken değişken veriler içeriyorsa veya türünün başlatılması pahalıysa ve uygulamada yaygın olarak kullanılıyorsa bağımlılık kapsayıcısına kapsam.
Hilt'i kullanın. Basit uygulamalarda Hilt veya manuel bağımlılık ekleme kullanın. Projeniz yeterince karmaşıksa Hilt'ı kullanın. Örneğin:
  • ViewModelleri ile birden çok ekran (entegrasyon)
  • WorkManager kullanımı - entegrasyon
  • Gezinme grafiğine kapsamlı ViewModel'ler gibi gezinme özelliklerinin ileri düzeyde kullanımı.

Test

Aşağıda test ile ilgili en iyi uygulamalardan bazıları verilmiştir:

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

Proje genel olarak bir hello dünya uygulaması kadar basit değilse projeyi en azından şunları kullanarak test etmelisiniz:

  • Akışlar dahil olmak üzere ViewModel'leri birim testi.
  • Veri katmanı varlıklarını birim testi. Yani depolar ve veri kaynakları.
  • CI'de geriye dönük test olarak faydalı olan kullanıcı arayüzü gezinme testleri.
Alay etmek yerine sahteleri tercih et. Daha fazla bilgi için Android'de test çiftleri kullanma dokümanlarını inceleyin.
StateFlow'ları test edin. StateFlow'ü test ederken:

Daha fazla bilgi için Android DAC'da test edilecekler kılavuzuna göz atın.

Modeller

Uygulamalarınızda model geliştirirken aşağıdaki en iyi uygulamaları göz önünde bulundurmanız gerekir:

Öneri Açıklama
Karmaşık uygulamalarda katman başına bir model oluşturun.

Karmaşık uygulamalarda, uygun 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ıfla eşleyebilir.
  • Depolar, DAO modellerini yalnızca kullanıcı arayüzü katmanının ihtiyaç duyduğu bilgilerle daha basit veri sınıflarıyla eşleyebilir.
  • ViewModel, UiState sınıflarındaki veri katmanı modellerini içerebilir.

Adlandırma kuralları

Kod tabanınızı adlandırırken aşağıdaki en iyi uygulamalardan yararlanabilirsiniz:

Öneri Açıklama
Adlandırma yöntemleri.
İsteğe bağlı
Yöntemler bir fiil öbeği olmalıdır. Örneğin, makePayment().
Mülkleri adlandırma.
İsteğe bağlı
Tesisler, bir isim öbeği olmalıdır. Örneğin, inProgressTopicSelection.
Veri akışlarını adlandırma.
İsteğe bağlı
Bir sınıf bir Flow akışı, LiveData veya başka bir akış gösterdiğinde adlandırma kuralı get{model}Stream()'tür. Örneğin, getAuthorStream(): Flow<Author> İşlev bir model listesi döndürüyorsa model adı çoğul halde olmalıdır: getAuthorsStream(): Flow<List<Author>>
Arayüz uygulamalarının adlandırması.
İsteğe bağlı
Arayüz uygulamalarında kullanılan adlar anlamlı olmalıdır. Daha iyi bir ad bulunamazsa ön ek olarak Default kullanılmalıdır. Örneğin, NewsRepository arayüzünde OfflineFirstNewsRepository veya InMemoryNewsRepository olabilir. Uygun bir ad bulamıyorsanız DefaultNewsRepository değerini kullanın. Sahte uygulamalar, FakeAuthorsRepository gibi Fake ile başlamalıdır.