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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • स्क्रीन-लेवल के कंपोज़ेबल,
  • व्यू में ऐक्टिविटी/फ़्रैगमेंट,
  • Jetpack Navigation का इस्तेमाल करते समय, डेस्टिनेशन या ग्राफ़.
दोबारा इस्तेमाल किए जा सकने वाले यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट में, सामान्य स्टेट होल्डर क्लास का इस्तेमाल करें. दोबारा इस्तेमाल किए जा सकने वाले यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट में जटिलता को मैनेज करने के लिए, सामान्य स्टेट होल्डर क्लास का इस्तेमाल करें. ऐसा करने पर, स्थिति को ऊपर ले जाया जा सकता है और बाहरी तौर पर कंट्रोल किया जा सकता है.
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 lifecycle के साथ काम करने के सबसे सही तरीके अपनाएं:

सुझाव ब्यौरा
लाइफ़साइकल की जानकारी वाले इफ़ेक्ट का इस्तेमाल, कंपोज़ेबल में करें. इसके लिए, 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 के लिए यूनिट टेस्ट, जिनमें फ़्लो भी शामिल हैं
  • डेटा लेयर की इकाइयों के लिए यूनिट टेस्ट. जैसे, रिपॉज़िटरी और डेटा सोर्स
  • यूज़र इंटरफ़ेस (यूआई) नेविगेशन टेस्ट, जो सीआई में रिग्रेशन टेस्ट के तौर पर काम आते हैं
मॉक के बजाय फ़ेक को प्राथमिकता दें. फ़ेक ऑब्जेक्ट इस्तेमाल करने के बारे में ज़्यादा जानने के लिए, Android में टेस्ट डबल का इस्तेमाल करना लेख पढ़ें.
StateFlows की जांच करें. StateFlow की टेस्टिंग करते समय, यह तरीका अपनाएं:

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

मॉडल

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

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

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

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

नाम रखने के नियम

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

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

अन्य संसाधन

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

दस्तावेज़

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