Android आर्किटेक्चर के लिए सुझाव

इस पेज पर, आर्किटेक्चर के सबसे सही तरीके और सुझाव दिए गए हैं. इनका इस्तेमाल करके, अपने ऐप्लिकेशन की क्वालिटी, मज़बूती, और स्केलेबिलिटी को बेहतर बनाएं. इनसे, ऐप्लिकेशन को बनाए रखना और उसकी जांच करना भी आसान हो जाता है.

यहां दिए गए सबसे सही तरीकों को विषय के हिसाब से ग्रुप किया गया है. हर सुझाव की एक प्राथमिकता होती है. इससे पता चलता है कि सुझाव कितना अहम है. प्राथमिकताओं की सूची यहां दी गई है:

  • इसका सुझाव दिया जाता है: इस तरीके को तब तक लागू करें, जब तक यह आपके तरीके से मेल खाता हो.
  • सुझाया गया: इस तरीके से आपके ऐप्लिकेशन को बेहतर बनाने में मदद मिल सकती है.
  • ज़रूरी नहीं है: कुछ मामलों में, इस तरीके से आपके ऐप्लिकेशन को बेहतर बनाया जा सकता है.

लेयर्ड आर्किटेक्चर

हमारा सुझाया गया लेयर्ड आर्किटेक्चर, अलग-अलग लेयर को अलग-अलग काम करने की सुविधा देता है. यह डेटा मॉडल से यूज़र इंटरफ़ेस (यूआई) को कंट्रोल करता है. साथ ही, यह सिंगल सोर्स ऑफ़ ट्रुथ के सिद्धांत का पालन करता है और एकतरफ़ा डेटा फ़्लो के सिद्धांतों का पालन करता है. लेयर्ड आर्किटेक्चर के लिए, यहां कुछ सबसे सही तरीके दिए गए हैं:

सुझाव ब्यौरा
डेटा लेयर को साफ़ तौर पर तय करें. डेटा लेयर, ऐप्लिकेशन के डेटा को ऐप्लिकेशन के बाकी हिस्सों के लिए उपलब्ध कराती है. साथ ही, इसमें आपके ऐप्लिकेशन के कारोबारी नियमों का ज़्यादातर हिस्सा शामिल होता है.
  • रिपॉज़िटरी बनाएं, भले ही उनमें सिर्फ़ एक डेटा सोर्स हो.
  • छोटे ऐप्लिकेशन में, डेटा लेयर टाइप को data पैकेज या मॉड्यूल में रखा जा सकता है.
साफ़ तौर पर तय की गई यूज़र इंटरफ़ेस (यूआई) लेयर का इस्तेमाल करें. यूआई लेयर, स्क्रीन पर ऐप्लिकेशन का डेटा दिखाती है. साथ ही, यह उपयोगकर्ता के इंटरैक्शन का मुख्य पॉइंट होता है. हमारा सुझाव है कि आप अपने ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) बनाने के लिए, Jetpack Compose का इस्तेमाल करें. यह एक मॉडर्न टूलकिट है.
  • छोटे ऐप्लिकेशन में, डेटा लेयर टाइप को ui पैकेज या मॉड्यूल में रखा जा सकता है.
यूज़र इंटरफ़ेस (यूआई) लेयर के सबसे सही तरीकों के बारे में ज़्यादा जानने के लिए, यूज़र इंटरफ़ेस (यूआई) लेयर देखें.
किसी रिपॉज़िटरी का इस्तेमाल करके, डेटा लेयर से ऐप्लिकेशन डेटा को ऐक्सेस करना.

पक्का करें कि यूज़र इंटरफ़ेस (यूआई) लेयर में मौजूद कॉम्पोनेंट, जैसे कि कंपोज़ेबल या व्यूमॉडल, डेटा सोर्स के साथ सीधे तौर पर इंटरैक्ट न करें. डेटा सोर्स के उदाहरण:

  • डेटाबेस, DataStore, SharedPreferences, Firebase API.
  • जीपीएस लोकेशन की जानकारी देने वाली कंपनियां.
  • ब्लूटूथ डेटा उपलब्ध कराने वाली कंपनियां.
  • नेटवर्क कनेक्टिविटी की स्थिति की जानकारी देने वाली कंपनियां.
कोरूटीन और फ़्लो का इस्तेमाल करें. लेयर के बीच कम्यूनिकेट करने के लिए, coroutines और flows का इस्तेमाल करें.

को-रूटीन के सबसे सही तरीकों के बारे में ज़्यादा जानने के लिए, Android में को-रूटीन के लिए सबसे सही तरीके लेख पढ़ें.

डोमेन लेयर का इस्तेमाल करें. अगर आपको कई ViewModels में डेटा लेयर के साथ इंटरैक्ट करने वाले कारोबारी नियमों का फिर से इस्तेमाल करना है या आपको किसी ViewModel के कारोबारी नियमों की जटिलता को कम करना है, तो इस्तेमाल के उदाहरणों के साथ डोमेन लेयर का इस्तेमाल करें

यूज़र इंटरफ़ेस (यूआई) लेयर

यूज़र इंटरफ़ेस (यूआई) लेयर का काम, स्क्रीन पर ऐप्लिकेशन का डेटा दिखाना है. साथ ही, यह उपयोगकर्ता के इंटरैक्शन के मुख्य पॉइंट के तौर पर काम करती है. यूज़र इंटरफ़ेस (यूआई) लेयर के लिए, यहां कुछ सबसे सही तरीके दिए गए हैं:

सुझाव ब्यौरा
एकतरफ़ा डेटा फ़्लो (यूडीएफ़) का पालन करें. एकतरफ़ा डेटा फ़्लो (यूडीएफ़) के सिद्धांतों का पालन करें. इसमें ViewModels, ऑब्ज़र्वर पैटर्न का इस्तेमाल करके यूज़र इंटरफ़ेस (यूआई) की स्थिति को दिखाते हैं और मेथड कॉल के ज़रिए यूज़र इंटरफ़ेस (यूआई) से ऐक्शन पाते हैं.
अगर आपके ऐप्लिकेशन के लिए AAC ViewModels के फ़ायदे लागू होते हैं, तो उनका इस्तेमाल करें. एएसी व्यूमॉडल का इस्तेमाल करके, कारोबार से जुड़े लॉजिक को मैनेज करें. साथ ही, ऐप्लिकेशन का डेटा फ़ेच करके, यूज़र इंटरफ़ेस (यूआई) की स्थिति को यूआई पर दिखाएं.

ViewModel इस्तेमाल करने के सबसे सही तरीकों के बारे में ज़्यादा जानने के लिए, आर्किटेक्चर से जुड़े सुझाव लेख पढ़ें.

ViewModels के फ़ायदों के बारे में ज़्यादा जानने के लिए, The ViewModel as a business logic state holder लेख पढ़ें.

लाइफ़साइकल के बारे में जानकारी रखने वाले यूज़र इंटरफ़ेस की स्थिति से जुड़ा डेटा इकट्ठा करने की सुविधा का इस्तेमाल करें. लाइफ़साइकल के बारे में जानकारी रखने वाले सही कोरूटीन बिल्डर, collectAsStateWithLifecycle का इस्तेमाल करके, यूज़र इंटरफ़ेस (यूआई) से यूज़र इंटरफ़ेस (यूआई) की स्थिति इकट्ठा करें.

collectAsStateWithLifecycle के बारे में ज़्यादा जानें.

ViewModel से यूज़र इंटरफ़ेस (यूआई) को इवेंट न भेजें. इवेंट को ViewModel में तुरंत प्रोसेस करें और इवेंट को हैंडल करने के नतीजे के साथ स्थिति को अपडेट करें. यूज़र इंटरफ़ेस (यूआई) इवेंट के बारे में ज़्यादा जानने के लिए, ViewModel इवेंट मैनेज करना लेख पढ़ें.
एक ही गतिविधि वाले ऐप्लिकेशन का इस्तेमाल करें. अगर आपके ऐप्लिकेशन में एक से ज़्यादा स्क्रीन हैं, तो स्क्रीन के बीच नेविगेट करने के लिए नेविगेशन 3 का इस्तेमाल करें. साथ ही, अपने ऐप्लिकेशन के डीप लिंक का इस्तेमाल करें.
Jetpack Compose का इस्तेमाल करें. फ़ोन, टैबलेट, फ़ोल्ड किए जा सकने वाले डिवाइसों, और Wear OS के लिए नए ऐप्लिकेशन बनाने के लिए, Jetpack Compose का इस्तेमाल करें.

यहां दिए गए स्निपेट में, लाइफ़साइकल के बारे में जानकारी रखने वाले तरीके से यूज़र इंटरफ़ेस (यूआई) की स्थिति को इकट्ठा करने का तरीका बताया गया है:

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

ViewModel

ViewModels, यूज़र इंटरफ़ेस (यूआई) की स्थिति के बारे में जानकारी देते हैं और डेटा लेयर को ऐक्सेस करते हैं. यहां ViewModels के लिए कुछ सबसे सही तरीके दिए गए हैं:

सुझाव ब्यौरा
ViewModel को Android लाइफ़साइकल से अलग रखें. ViewModel में, लाइफ़साइकल से जुड़े किसी भी टाइप का रेफ़रंस न रखें. Activity, Context या Resources को डिपेंडेंसी के तौर पर पास न करें. अगर ViewModel में किसी चीज़ के लिए Context की ज़रूरत है, तो ध्यान से देखें कि वह सही लेयर में है या नहीं.
कोरूटीन और फ़्लो का इस्तेमाल करें.

ViewModel, डेटा या डोमेन लेयर के साथ इन तरीकों से इंटरैक्ट करता है:

  • ऐप्लिकेशन का डेटा पाने के लिए Kotlin फ़्लो
  • viewModelScope का इस्तेमाल करके कार्रवाइयां करने के लिए suspend फ़ंक्शन
स्क्रीन लेवल पर ViewModels का इस्तेमाल करें.

यूज़र इंटरफ़ेस (यूआई) के दोबारा इस्तेमाल किए जा सकने वाले हिस्सों में ViewModels का इस्तेमाल न करें. आपको ViewModels का इस्तेमाल इनमें करना चाहिए:

  • स्क्रीन-लेवल के कंपोज़ेबल
  • Jetpack Navigation का इस्तेमाल करते समय डेस्टिनेशन या ग्राफ़

ज़्यादा जटिल कंपोज़ेबल या ऐसे कंपोज़ेबल जिनके व्यवहार में स्टेट के आधार पर बदलाव होता है उनके लिए, rememberViewModelStoreOwner() का इस्तेमाल करके ViewModel को सीधे तौर पर कंपोज़ेबल की कॉल साइट पर स्कोप करें.

फिर से इस्तेमाल किए जा सकने वाले यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट में, सामान्य स्टेट होल्डर क्लास का इस्तेमाल करें. फिर से इस्तेमाल किए जा सकने वाले यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट में जटिलता को मैनेज करने के लिए, सामान्य स्टेट होल्डर क्लास का इस्तेमाल करें. ऐसा करने पर, स्टेट को ऊपर ले जाया जा सकता है और इसे बाहरी तौर पर कंट्रोल किया जा सकता है.
AndroidViewModel का इस्तेमाल न करें. AndroidViewModel के बजाय, ViewModel क्लास का इस्तेमाल करें. ViewModel में Application क्लास का इस्तेमाल न करें. इसके बजाय, डिपेंडेंसी को यूज़र इंटरफ़ेस (यूआई) या डेटा लेयर में ले जाएं.
यूज़र इंटरफ़ेस (यूआई) की स्थिति को दिखाना. अपने ViewModels को, यूज़र इंटरफ़ेस (यूआई) को डेटा दिखाने के लिए, uiState नाम की एक प्रॉपर्टी का इस्तेमाल करना चाहिए. अगर यूज़र इंटरफ़ेस (यूआई) में अलग-अलग तरह का डेटा दिखता है, तो वीएम यूज़र इंटरफ़ेस (यूआई) की कई स्टेट प्रॉपर्टी दिखा सकता है.
  • uiState को StateFlow बनाएं.
  • अगर डेटा, क्रम के हिसाब से अन्य लेयर से आता है, तो WhileSubscribed(5000) नीति के साथ stateIn ऑपरेटर का इस्तेमाल करके uiState बनाएं. (कोड का यह उदाहरण देखें.)
  • अगर डेटा लेयर से डेटा की कोई स्ट्रीम नहीं आ रही है, तो ऐसे आसान मामलों के लिए, MutableStateFlow का इस्तेमाल किया जा सकता है. इसे न बदलने वाले StateFlow के तौर पर दिखाया जाता है.
  • ${Screen}UiState को एक ऐसे डेटा क्लास के तौर पर इस्तेमाल किया जा सकता है जिसमें डेटा, गड़बड़ियां, और लोडिंग सिग्नल शामिल हो सकते हैं. अगर अलग-अलग स्थितियां एक्सक्लूसिव हैं, तो इस क्लास को सील की गई क्लास के तौर पर भी इस्तेमाल किया जा सकता है.

यहां दिए गए स्निपेट में, ViewModel से यूज़र इंटरफ़ेस (यूआई) की स्थिति को दिखाने का तरीका बताया गया है:

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

    // ...
}

लाइफ़साइकल

Activity लाइफ़साइकल के साथ काम करने के लिए, सबसे सही तरीके अपनाएं:

सुझाव ब्यौरा
लाइफ़साइकल के बारे में जानकारी रखने वाले इफ़ेक्ट का इस्तेमाल कंपोज़ेबल में करें. इसके लिए, Activity लाइफ़साइकल कॉलबैक को बदलने के बजाय, इनका इस्तेमाल करें.

यूज़र इंटरफ़ेस (यूआई) से जुड़े टास्क चलाने के लिए, Activity लाइफ़साइकल के तरीकों को ओवरराइड न करें. जैसे, onResume. इसके बजाय, Compose के LifecycleEffects या लाइफ़साइकल के बारे में जानकारी रखने वाले को-रूटीन स्कोप का इस्तेमाल करें:

  • गतिविधि शुरू और बंद होने पर, एक साथ कई काम करने के लिए LifecycleStartEffect का इस्तेमाल करें.
  • जब आपकी गतिविधि फिर से शुरू होती है और रुकती है, तब सिंक्रोनस तरीके से काम करने के लिए LifecycleResumeEffect का इस्तेमाल करें.
  • लाइफ़साइकल इवेंट के जवाब में एसिंक्रोनस टास्क पूरा करने के लिए, repeatOnLifecycle का इस्तेमाल करें.
  • collectAsStateWithLifecycle का इस्तेमाल करके, फ़्लो से एसिंक्रोनस डेटा इकट्ठा करें.

यहां दिए गए स्निपेट में, लाइफ़साइकल की किसी स्थिति के हिसाब से कार्रवाइयां करने का तरीका बताया गया है:

  @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)
        }
    }
  }

डिपेंडेंसी हैंडल करता है

कॉम्पोनेंट के बीच डिपेंडेंसी मैनेज करते समय, इन सबसे सही तरीकों का पालन करें:

सुझाव ब्यौरा
डिपेंडेंसी इंजेक्शन का इस्तेमाल करें. जब भी हो सके, डिपेंडेंसी इंजेक्शन के सबसे सही तरीकों का इस्तेमाल करें. इनमें मुख्य रूप से कंस्ट्रक्टर इंजेक्शन शामिल है.
ज़रूरत पड़ने पर, किसी कॉम्पोनेंट के लिए स्कोप तय करें. जब टाइप में ऐसा डेटा शामिल हो जिसे बदला जा सकता है और जिसे शेयर करने की ज़रूरत हो या टाइप को शुरू करने में ज़्यादा समय लगता हो और इसका इस्तेमाल ऐप्लिकेशन में बड़े पैमाने पर किया जाता हो, तब डिपेंडेंसी कंटेनर को स्कोप करें.
Hilt का इस्तेमाल करें. आसान ऐप्लिकेशन में, Hilt या मैन्युअल डिपेंडेंसी इंजेक्शन का इस्तेमाल करें. अगर आपका प्रोजेक्ट काफ़ी जटिल है, तो Hilt का इस्तेमाल करें. उदाहरण के लिए, अगर इसमें इनमें से कोई भी चीज़ शामिल है:
  • ViewModel के साथ एक से ज़्यादा स्क्रीन
  • WorkManager का इस्तेमाल करता है
  • इसमें नेविगेशन बैक स्टैक के स्कोप वाले ViewModels होते हैं

जांच करना

टेस्टिंग के लिए, यहां कुछ सबसे सही तरीके दिए गए हैं:

सुझाव ब्यौरा
जानें कि क्या टेस्ट करना है.

अगर प्रोजेक्ट "नमस्ते, दुनिया के लोगों" जैसे आसान ऐप्लिकेशन के लिए नहीं है, तो उसकी जांच करें. कम से कम यह जानकारी शामिल करें:

  • ViewModel के लिए यूनिट टेस्ट, जिनमें फ़्लो भी शामिल हैं
  • डेटा लेयर की इकाइयों के लिए यूनिट टेस्ट—यानी कि रिपॉज़िटरी और डेटा सोर्स
  • यूज़र इंटरफ़ेस (यूआई) नेविगेशन टेस्ट, जो सीआई में रिग्रेशन टेस्ट के तौर पर काम आते हैं
  • ऐप्लिकेशन के स्टार्टअप और यूज़र इंटरफ़ेस (यूआई) रेंडरिंग को मेज़र करने के लिए, Macrobenchmark का इस्तेमाल करके परफ़ॉर्मेंस टेस्ट
मॉक के बजाय फ़ेक को प्राथमिकता दें. फ़ेक का इस्तेमाल करने के बारे में ज़्यादा जानने के लिए, Android में टेस्ट डबल का इस्तेमाल करना लेख पढ़ें.
StateFlows की जांच करें. StateFlow की टेस्टिंग करते समय, यह तरीका अपनाएं:

ज़्यादा जानकारी के लिए, Android में क्या टेस्ट करें और अपने Compose लेआउट की जांच करें लेख पढ़ें.

परफ़ॉर्मेंस

परफ़ॉर्मेंस को बेहतर बनाने के लिए, यहां कुछ सबसे सही तरीके दिए गए हैं:

सुझाव ब्यौरा
अपने ऐप्लिकेशन को छोटा करने और उसे ऑप्टिमाइज़ करने के लिए, R8 का इस्तेमाल करें. अपने बिल्ड कॉन्फ़िगरेशन में, R8 को फ़ुल मोड में चालू करें. इससे इस्तेमाल न होने वाला कोड हट जाएगा, क्लास को अस्पष्ट कर दिया जाएगा, और रनटाइम परफ़ॉर्मेंस को बेहतर बनाने के लिए कोड को फिर से लिखा जाएगा.
बेसलाइन प्रोफ़ाइल और स्टार्टअप प्रोफ़ाइल लागू करें. ज़रूरी कोड पाथ को पहले से कंपाइल करने के लिए, बेसलाइन प्रोफ़ाइल और स्टार्टअप प्रोफ़ाइल जनरेट करें. इससे स्टार्टअप लेटेंसी (टीटीआईडी और टीटीएफ़डी) में काफ़ी कमी आती है. साथ ही, जंक और एएनआर की समस्याएं कम होती हैं.
Macrobenchmark की मदद से परफ़ॉर्मेंस टेस्ट करें. अपने ऐप्लिकेशन की परफ़ॉर्मेंस की जांच करने और रिग्रेशन को रोकने के लिए, Macrobenchmark लाइब्रेरी का इस्तेमाल करें.

मॉडल

अपने ऐप्लिकेशन में मॉडल डेवलप करते समय, इन सबसे सही तरीकों को ध्यान में रखें:

सुझाव ब्यौरा
जटिल ऐप्लिकेशन में, हर लेयर के लिए एक मॉडल बनाएं.

जटिल ऐप्लिकेशन में, जब ज़रूरत हो, तब अलग-अलग लेयर या कॉम्पोनेंट में नए मॉडल बनाएं. यहां दिए गए उदाहरण देखें:

  • रिमोट डेटा सोर्स, नेटवर्क से मिले मॉडल को एक आसान क्लास में मैप कर सकता है. इसमें सिर्फ़ वह डेटा होता है जिसकी ऐप्लिकेशन को ज़रूरत होती है.
  • रिपॉज़िटरी, DAO मॉडल को आसान डेटा क्लास में मैप कर सकती हैं. इसके लिए, सिर्फ़ यूज़र इंटरफ़ेस (यूआई) लेयर को ज़रूरी जानकारी की ज़रूरत होती है.
  • ViewModel, UiState क्लास में डेटा लेयर मॉडल शामिल कर सकता है.

नाम रखने के तरीके

अपने कोडबेस का नाम रखते समय, आपको इन सबसे सही तरीकों के बारे में पता होना चाहिए:

सुझाव ब्यौरा
नाम रखने के तरीके.
ज़रूरी नहीं है
तरीकों के नाम रखने के लिए, क्रिया वाक्यांशों का इस्तेमाल करें. उदाहरण के लिए, makePayment().
प्रॉपर्टी के नाम.
ज़रूरी नहीं है
प्रॉपर्टी के नाम के लिए संज्ञा वाक्यांशों का इस्तेमाल करें. उदाहरण के लिए, inProgressTopicSelection.
डेटा स्ट्रीम के नाम रखना.
ज़रूरी नहीं है
जब कोई क्लास, फ़्लो स्ट्रीम या कोई अन्य स्ट्रीम दिखाती है, तो नाम रखने का तरीका get{model}Stream होता है. उदाहरण के लिए, getAuthorStream(): Flow<Author>. अगर फ़ंक्शन, मॉडल की सूची दिखाता है, तो मॉडल के नाम का प्लुरल फ़ॉर्म इस्तेमाल करें: getAuthorsStream(): Flow<List<Author>>.
इंटरफ़ेस लागू करने के लिए नेमिंग.
ज़रूरी नहीं है
इंटरफ़ेस को लागू करने के लिए, काम के नामों का इस्तेमाल करें. अगर कोई बेहतर नाम नहीं मिलता है, तो प्रीफ़िक्स के तौर पर Default का इस्तेमाल करें. उदाहरण के लिए, NewsRepository इंटरफ़ेस के लिए, आपके पास OfflineFirstNewsRepository या InMemoryNewsRepository हो सकता है. अगर आपको कोई अच्छा नाम नहीं मिल रहा है, तो DefaultNewsRepository का इस्तेमाल करें. फ़र्ज़ी तौर पर लागू किए गए प्रीफ़िक्स को Fake से प्रीफ़िक्स करें. जैसे, FakeAuthorsRepository.

अन्य संसाधन

Android के आर्किटेक्चर के बारे में ज़्यादा जानने के लिए, यहां दिए गए अतिरिक्त संसाधन देखें:

दस्तावेज़

कॉन्टेंट देखता है