Computer >> कंप्यूटर >  >> प्रणाली >> Android

एंड्रॉइड पर प्रो की तरह मॉडल-व्यू-व्यूमॉडल का उपयोग कैसे करें

इस लेख में मेरा लक्ष्य यह बताना है कि क्यों मॉडल-व्यू-व्यूमॉडल आर्किटेक्चरल पैटर्न जीयूआई आर्किटेक्चर के प्रेजेंटेशन लॉजिक के संबंध में कुछ स्थितियों में चिंताओं का एक बहुत ही अजीब अलगाव प्रस्तुत करता है।

हम एमवीवीएम के दो प्रकारों का पता लगाएंगे (वहां है नहीं इसे करने का सिर्फ एक तरीका), और परियोजना की आवश्यकताओं के आधार पर आप एक संस्करण को दूसरे पर क्यों पसंद कर सकते हैं।

MVVM बनाम MVP/MVC?

इस बात की काफी संभावना है कि मेरे लाइव संडे प्रश्नोत्तर सत्र के दौरान मुझसे जो सबसे आम प्रश्न पूछा जाता है, वह कुछ इस प्रकार है:

MVVM बनाम MVP/MVC?

जब भी मुझसे यह प्रश्न पूछा जाता है, तो मैं तुरंत इस विचार पर जोर देता हूं कि कोई भी GUI आर्किटेक्चर सभी स्थितियों में अच्छा काम नहीं करता है।

क्यों, आप पूछ सकते हैं? किसी दिए गए एप्लिकेशन के लिए सर्वोत्तम आर्किटेक्चर (या कम से कम एक अच्छा विकल्प) हाथ की आवश्यकताओं पर दृढ़ता से निर्भर करता है।

आइए संक्षेप में सोचें कि यह शब्द क्या है आवश्यकताएं वास्तव में इसका अर्थ है:

  • आपका UI कितना जटिल है? एक साधारण यूआई को आम तौर पर इसे समन्वित करने के लिए जटिल तर्क की आवश्यकता नहीं होती है, जबकि एक जटिल यूआई को सुचारू रूप से काम करने के लिए व्यापक तर्क और बारीक नियंत्रण की आवश्यकता हो सकती है।
  • आप परीक्षण के बारे में कितना ध्यान रखते हैं? सामान्यतया, कक्षाएं जो ढांचे और ओएस (विशेष रूप से उपयोगकर्ता इंटरफ़ेस . के साथ कसकर जुड़ी होती हैं ) परीक्षण के लिए अतिरिक्त कार्य की आवश्यकता है।
  • आप कितना पुन:प्रयोज्य और अमूर्तता को बढ़ावा देना चाहते हैं? क्या होगा यदि आप अपने एप्लिकेशन के बैक एंड, डोमेन और यहां तक ​​कि प्रस्तुति तर्क को विभिन्न प्लेटफॉर्म पर साझा करना चाहते हैं?
  • क्या आप स्वभाव से व्यावहारिक हैं , पूर्णतावादी , आलसी , या उपरोक्त सभी अलग-अलग समय पर, अलग-अलग परिस्थितियों में?

मुझे एक लेख लिखना अच्छा लगेगा जहां मैं विस्तार से चर्चा करता हूं कि एमवीवीएम ऊपर सूचीबद्ध आवश्यकताओं और चिंताओं के संबंध में कैसे काम करता है। दुर्भाग्य से, आप में से कुछ लोगों को यह सोचकर गुमराह किया गया है कि एमवीवीएम करने का केवल एक ही तरीका है।

इसके बजाय, मैं एमवीवीएम के सामान्य विचार के दो अलग-अलग दृष्टिकोणों पर चर्चा करूंगा जो बहुत अलग लाभ और नुकसान प्रस्तुत करते हैं। लेकिन पहले, आइए सामान्य विचार से शुरू करें।

आप अपने व्यू क्लासेस का संदर्भ नहीं देंगे

मेरे उन मित्रों के लिए जो पुरानी अंग्रेज़ी नहीं पढ़ सकते:आप दृश्य कक्षाओं का संदर्भ नहीं दे सकते हैं ।"

ViewModel नाम का उपयोग करने के अलावा (जो स्वयं भ्रमित है यदि वर्ग तर्क . से भरा है ), एमवीवीएम आर्किटेक्चर का एक आयरन-क्लैड नियम यह है कि आप व्यूमोडेल से कभी भी व्यू का संदर्भ नहीं दे सकते हैं।

अब, भ्रम का पहला क्षेत्र इस शब्द "संदर्भ" से उत्पन्न हो सकता है, जिसे मैं कई अलग-अलग स्तरों के शब्दजाल का उपयोग करके पुन:स्थापित करूंगा:

  • आपके ViewModels में किसी भी दृश्य का कोई संदर्भ (सदस्य चर, गुण, परिवर्तनशील/अपरिवर्तनीय फ़ील्ड) नहीं हो सकता है
  • आपके व्यूमॉडल किसी व्यू पर निर्भर नहीं हो सकते हैं
  • हो सकता है कि आपके व्यूमॉडल सीधे आपके विचारों से बात न करें

अब, एंड्रॉइड प्लेटफॉर्म पर, इस नियम का कारण केवल यह नहीं है कि इसे तोड़ना बुरा है क्योंकि ऐसा लगता है कि सॉफ़्टवेयर आर्किटेक्चर के बारे में जानने वाले किसी व्यक्ति ने आपको बताया कि यह खराब है।

आर्किटेक्चर कंपोनेंट्स से व्यूमोडेल क्लास का उपयोग करते समय (जिसे इसके उदाहरण के लिए डिज़ाइन किया गया है जारी रखें Fragment/गतिविधि जीवनचक्र से अधिक लंबा उचित होने पर ), एक दृश्य को संदर्भित करना गंभीर स्मृति रिसाव के लिए पूछ रहा है ।

एमवीवीएम आम तौर पर ऐसे संदर्भों की अनुमति क्यों नहीं देता है, इसका लक्ष्य काल्पनिक रूप से . है व्यू और व्यूमोडेल दोनों को परीक्षण और लिखने में आसान बनाने के लिए।

अन्य लोग यह भी बता सकते हैं कि यह ViewModels की पुन:प्रयोज्यता को बढ़ावा देता है, लेकिन यह ठीक वही है जहां चीजें इस पैटर्न के साथ टूट जाती हैं

इससे पहले कि हम कोड देखें, कृपया ध्यान दें कि मैं व्यक्तिगत रूप से LiveData का उपयोग नहीं करता मेरे अपने उत्पादन कोड में। मैं इन दिनों अपना खुद का प्रकाशक-सब्सक्राइबर पैटर्न लिखना पसंद करता हूं, लेकिन जो मैं नीचे कहता हूं वह किसी भी पुस्तकालय पर लागू होता है जो व्यूमोडेल से व्यू तक पबसब/ऑब्जर्वर पैटर्न लिंक की अनुमति देता है।

इस लेख के साथ एक वीडियो ट्यूटोरियल है जिसमें कई समान विचारों को शामिल किया गया है:

ViewLogic + ViewModel या View + ViewModelController?

जब मैंने पिछले खंड में "ब्रेक डाउन" कहा था, तो मेरे कहने का मतलब यह नहीं है कि पैटर्न सचमुच टूट जाता है। मेरा मतलब है कि यह (कम से कम) दो अलग-अलग दृष्टिकोणों में टूट जाता है, जिनके बहुत अलग रूप, लाभ और परिणाम होते हैं।

आइए इन दो दृष्टिकोणों पर विचार करें, और जब आप एक को दूसरे पर पसंद करना चाहें।

एंड्रॉइड पर प्रो की तरह मॉडल-व्यू-व्यूमॉडल का उपयोग कैसे करें
बोरोमिर बताते हैं कि एमवीवीएम कोई जादू की छड़ी नहीं है जो आपके एप्लिकेशन के प्रेजेंटेशन लॉजिक को गायब कर देती है।

पहला तरीका:पुन:प्रयोज्य दृश्य मॉडलों को प्राथमिकता दें

जहां तक ​​मैं बता सकता हूं, एमवीवीएम को लागू करने वाले ज्यादातर लोग इसे व्यूमोडेल की पुन:प्रयोज्यता को बढ़ावा देने का लक्ष्य बनाते हैं, ताकि उन्हें n के लिए पुन:उपयोग किया जा सके। विभिन्न दृश्यों की संख्या (अनेक-से-एक अनुपात)।

सरल शब्दों में, आप इस पुन:प्रयोज्यता को प्राप्त करने के दो तरीके हैं:

  • किसी विशिष्ट दृश्य का संदर्भ न देकर। उम्मीद है कि इस समय यह आपके लिए खबर नहीं है।
  • जानकर UI . के विवरण के बारे में जितना संभव हो उतना कम सामान्य तौर पर

दूसरा बिंदु अस्पष्ट या प्रति-सहज लग सकता है (यह किसी ऐसी चीज़ के बारे में कुछ भी कैसे जान सकता है जिसका वह संदर्भ नहीं देता है?), इसलिए मुझे लगता है कि यह कुछ कोड देखने का समय है:

class NoteViewModel(val repo: NoteRepo): ViewModel(){
    //Note: you may also publish data to the View via Databinding, RxJava Observables, and other approaches. Although I do not like to use LiveData in back end classes, it works great with Android front end with AAC
    val noteState: MutableLiveData<Note>()
    //...
    fun handleEvent(event: NoteEvent) {
        when (event) {
            is NoteEvent.OnStart -> getNote(event.noteId)
            //...
        }
    }
    private fun getNote(noteId: String){
        noteState.value = repo.getNote(noteId)
    }
}

हालांकि यह एक बहुत ही सरल उदाहरण है, मुद्दा यह है कि केवल एक चीज जिसे यह विशेष रूप से ViewModel सार्वजनिक रूप से उजागर करता है (हैंडलएवेंट फ़ंक्शन के अलावा), एक साधारण नोट ऑब्जेक्ट है:

data class Note(val creationDate:String,
                val contents:String,
                val imageUrl: String,
                val creator: User?)

इस विशेष दृष्टिकोण के साथ, व्यूमोडेल न केवल एक विशेष दृश्य से, बल्कि विवरण, और विस्तार से, प्रस्तुति तर्क से अच्छी तरह से और सही मायने में अलग हो गया है। किसी विशेष दृश्य का।

अगर मैं जो कह रहा हूं वह अभी भी अस्पष्ट लगता है, तो मैं वादा करता हूं कि एक बार जब मैं दूसरे दृष्टिकोण का वर्णन करूंगा तो यह स्पष्ट हो जाएगा।

हालांकि मेरा पिछला शीर्षक, “ViewLogic + ViewModel… " का उपयोग या गंभीरता से लेने के लिए नहीं है, मेरा मतलब है कि बहुत ही डिकूप्ड और पुन:उपयोग करने योग्य व्यूमॉडल्स होने से, अब हम स्क्रीन पर इस नोट ऑब्जेक्ट को प्रस्तुत/बाध्य करने का तरीका जानने का काम करने के लिए स्वयं दृश्य पर निर्भर हैं।

हममें से कुछ लोग व्यू क्लासेस को लॉजिक से भरना पसंद नहीं करते हैं।

यह वह जगह है जहां चीजें बहुत गंदी हो जाती हैं और परियोजना पर निर्भर होती हैं आवश्यकताएं . मैं यह नहीं कह रहा हूं कि व्यू क्लासेस को लॉजिक से भरना जैसे…:

private fun observeViewModel() {
    viewModel.notes.observe(
        viewLifecycleOwner,
        Observer { notes: List<Note> ->
            if (notes.isEmpty()) showEmptyState()
            else showNoteList(notes)
        }
    )
   //..
}

…है हमेशा एक बुरी बात है, लेकिन कक्षाएं जो मंच से कसकर जुड़ी हुई हैं (जैसे टुकड़े) परीक्षण करना मुश्किल है, और उनमें तर्क वाले वर्ग परीक्षण करने के लिए सबसे महत्वपूर्ण वर्ग हैं!

एक शब्द में, किसी भी अच्छी वास्तुकला का स्वर्णिम सिद्धांत जिसे मैं मानता हूं उसे लागू करने में विफलता है:चिंताओं का पृथक्करण .

मेरी निजी राय यह है कि चिंताओं के पृथक्करण को बहुत उच्च स्तर पर लागू करना इसके लायक है। लेकिन कोई गलती न करें कि बहुत सारे नकद गाय के आवेदन ऐसे लोगों द्वारा लिखे गए हैं जिनके पास इसका अर्थ के बारे में मामूली सुराग नहीं है।

किसी भी मामले में, जिस दृष्टिकोण पर हम आगे चर्चा करेंगे, जबकि इसके अपने दुष्प्रभाव हैं , एक बार फिर से प्रस्तुति तर्क को दृश्य से हटा देता है।

खैर, इसमें से अधिकांश वैसे भी।

दूसरा तरीका:विनम्र दृश्य, कंट्रोल-फ्रीक व्यूमॉडल

कभी-कभी आपके व्यूज (जो कि व्यूमॉडल्स की पुन:उपयोगिता को प्राथमिकता देने का परिणाम है) पर ठीक-ठाक नियंत्रण नहीं होना, वास्तव में बेकार है।

पिछले दृष्टिकोण को अंधाधुंध तरीके से लागू करने के बारे में मुझे और भी कम उत्साहित करने के लिए, मुझे लगता है कि मैं अक्सर नहीं एक ViewModel का पुन:उपयोग करने की आवश्यकता है

विडंबना यह है कि, "बहुत अधिक अमूर्तता" एमवीवीएम पर एमवीपी की एक आम आलोचना है।

ऐसा कहा जा रहा है कि, व्यू पर इस बढ़िया नियंत्रण को पुनः प्राप्त करने के लिए कोई भी व्यूमोडेल में एक संदर्भ वापस नहीं जोड़ सकता है। यह मूल रूप से केवल एमवीपी + मेमोरी लीक होगा (मान लीजिए कि आप अभी भी एएसी से व्यूमोडेल का उपयोग कर रहे हैं)।

तो विकल्प यह है कि आप अपने ViewModels को इस प्रकार बनाएं कि उनमें लगभग सभी व्यवहार शामिल हों। , राज्य , और प्रस्तुति तर्क किसी दिए गए दृश्य का। दृश्य अभी भी निश्चित रूप से ViewModel से जुड़ा होना चाहिए, लेकिन दृश्य के बारे में पर्याप्त विवरण ViewModel में मौजूद हैं कि दृश्य के कार्य एक लाइनर (छोटे अपवादों के साथ) तक कम हो जाते हैं।

मार्टिन फाउलर के नामकरण सम्मेलनों में, इसे पैसिव व्यू/स्क्रीन के रूप में जाना जाता है। इस दृष्टिकोण के लिए अधिक सामान्यतः लागू नाम विनम्र वस्तु पैटर्न . है ।

इसे प्राप्त करने के लिए, आपके पास व्यू में मौजूद प्रत्येक नियंत्रण या विजेट के लिए अनिवार्य रूप से आपके व्यूमोडेल के पास एक अवलोकन योग्य क्षेत्र होना चाहिए (हालांकि आप इसे प्राप्त करते हैं - डेटा बाध्यकारी, आरएक्स, लाइवडाटा, जो भी हो):

class UserViewModel(
    val repo: IUserRepository,
){

    //The actual data model is kept private to avoid unwanted tampering
    private val userState = MutableLiveData<User>()

    //Control Logic
    internal val authAttemptState = MutableLiveData<Unit>()
    internal val startAnimation = MutableLiveData<Unit>()

    //UI Binding
    internal val signInStatusText = MutableLiveData<String>()
    internal val authButtonText = MutableLiveData<String>()
    internal val satelliteDrawable = MutableLiveData<String>()

    private fun showErrorState() {
        signInStatusText.value = LOGIN_ERROR
        authButtonText.value = SIGN_IN
        satelliteDrawable.value = ANTENNA_EMPTY
    }
    //...
}

इसके बाद, व्यू को अभी भी व्यूमोडेल तक खुद को तार करने की आवश्यकता होगी, लेकिन ऐसा करने के लिए आवश्यक कार्यों को लिखना बहुत आसान हो जाता है:

class LoginView : Fragment() {

    private lateinit var viewModel: UserViewModel
    //...
    
    //Create and bind to ViewModel
    override fun onStart() {
        super.onStart()
        viewModel = ViewModelProviders.of(
        //...   
        ).get(UserViewModel::class.java)

        //start background anim
        (root_fragment_login.background as AnimationDrawable).startWithFade()

        setUpClickListeners()
        observeViewModel()

        viewModel.handleEvent(LoginEvent.OnStart)
    }

    private fun setUpClickListeners() {
      //...
    }

    private fun observeViewModel() {
        viewModel.signInStatusText.observe(
            viewLifecycleOwner,
            Observer {
                //"it" is the value of the MutableLiveData object, which is inferred to be a String automatically
                lbl_login_status_display.text = it
            }
        )

        viewModel.authButtonText.observe(
            viewLifecycleOwner,
            Observer {
                btn_auth_attempt.text = it
            }
        )

        viewModel.startAnimation.observe(
            viewLifecycleOwner,
            Observer {
                imv_antenna_animation.setImageResource(
                    resources.getIdentifier(ANTENNA_LOOP, "drawable", activity?.packageName)
                )
                (imv_antenna_animation.drawable as AnimationDrawable).start()
            }
        )

        viewModel.authAttemptState.observe(
            viewLifecycleOwner,
            Observer { startSignInFlow() }
        )

        viewModel.satelliteDrawable.observe(
            viewLifecycleOwner,
            Observer {
                imv_antenna_animation.setImageResource(
                    resources.getIdentifier(it, "drawable", activity?.packageName)
                )
            }
        )
    }

आप इस उदाहरण के लिए पूरा कोड यहां पा सकते हैं।

जैसा कि आपने शायद गौर किया है, हम शायद इस ViewModel कहीं और का पुन:उपयोग नहीं करने जा रहे हैं . साथ ही, हमारा दृष्टिकोण पर्याप्त रूप से विनम्र हो गया है (आपके मानकों और कोड कवरेज के लिए वरीयताओं के आधार पर), और लिखना बहुत आसान है।

कभी-कभी आप ऐसी स्थितियों में भाग लेंगे जहां आपको प्रस्तुति तर्क के वितरण के बीच किसी प्रकार का आधा उपाय खोजना होगा Views और ViewModels के बीच, जो इनमें से किसी भी दृष्टिकोण का कड़ाई से पालन नहीं करता है।

मैं एक दृष्टिकोण की दूसरे पर वकालत नहीं कर रहा हूं, बल्कि मौजूदा आवश्यकताओं के आधार पर आपको अपने दृष्टिकोण में लचीला होने के लिए प्रोत्साहित कर रहा हूं।

वरीयताओं और आवश्यकताओं के आधार पर अपना आर्किटेक्चर चुनें

इस लेख का उद्देश्य दो अलग-अलग दृष्टिकोणों को देखना था जो एक डेवलपर एंड्रॉइड प्लेटफॉर्म पर एमवीवीएम स्टाइल जीयूआई आर्किटेक्चर के निर्माण के संदर्भ में ले सकता है (कुछ अन्य प्लेटफॉर्म पर ले जाने के साथ)।

सच में, हम इन दो दृष्टिकोणों में भी छोटे अंतरों के बारे में अधिक विशिष्ट जानकारी प्राप्त कर सकते हैं।

  • क्या दृश्य को उसके पास मौजूद प्रत्येक विजेट/नियंत्रण के लिए एक फ़ील्ड का निरीक्षण करना चाहिए, या उसे एक फ़ील्ड का निरीक्षण करना चाहिए जो एक मॉडल को प्रकाशित करता है पूरे दृश्य को हर बार नए सिरे से प्रस्तुत करने के लिए?
  • हो सकता है कि हम अपने व्यूमॉडल्स को एक-से-एक बनाने से बच सकें, जबकि अपने विचारों को विनम्र वस्तुओं के रूप में रखते हुए, बस मिश्रण में प्रस्तुतकर्ता या नियंत्रक जैसी कोई चीज़ जोड़कर?

बात सस्ती है, और मैं आपको सलाह देता हूं कि कोड में . इन चीजों को आजमाएं और सीखें ताकि आपको यह बताने के लिए कि क्या करना है, आपको मेरे जैसे लोगों पर निर्भर रहने की आवश्यकता नहीं है।

अंततः, मुझे लगता है कि दो तत्व जो एक महान वास्तुकला का निर्माण करते हैं, निम्नलिखित बातों पर आते हैं:

सबसे पहले, कई दृष्टिकोणों के साथ तब तक खेलें जब तक कि आपको वह नहीं मिल जाता जिसे आप पसंद करते हैं . यह वास्तव में प्रत्येक शैली में एक एप्लिकेशन (यह सरल हो सकता है) बनाकर और सही लगता है देखकर सबसे अच्छा किया जाता है। ।

दूसरे, यह समझें कि प्राथमिकताएं एक तरफ, अलग-अलग शैलियों में अलग-अलग घाटे के बदले अलग-अलग लाभों पर जोर दिया जाएगा। अंततः, आप अंध विश्वास के बजाय परियोजना आवश्यकताओं की अपनी समझ के आधार पर अच्छे विकल्प चुनने में सक्षम होंगे ।

सॉफ़्टवेयर आर्किटेक्चर के बारे में अधिक जानें:

सामाजिक

https://www.instagram.com/rkay301/
https://www.facebook.com/wiseassblog/
https://twitter.com/wiseass301
https://wiseassblog.com/


  1. एंड्रॉइड पर एक प्रो की तरह स्क्रीनशॉट और छवियों को कैसे एनोटेट करें

    यदि आप Android पर मोबाइल स्क्रीनशॉट को एनोटेट करना चाहते हैं, तो आपके फ़ोन में पहले से ही अंतर्निहित स्क्रीनशॉट मार्किंग सुविधाएँ हो सकती हैं। जबकि सभी फोन में यह उपयोगी कार्यक्षमता नहीं होती है, आप इसे तृतीय-पक्ष एप्लिकेशन का उपयोग करके आसानी से जोड़ सकते हैं। आइए बात करते हैं कि एंड्रॉइड पर तस्वी

  1. आईटी प्रो की तरह विंडोज 11/10 टास्क मैनेजर का उपयोग कैसे करें

    विंडोज 11/10/8 की सबसे अच्छी विशेषताओं में से एक जो मुझे पसंद है वह है टास्क मैनेजर। विनम्र कार्य प्रबंधक वर्षों में विकसित हुआ है और अब नया विंडोज 11/10/8 कार्य प्रबंधक, बहुत सारी जानकारी प्रदान करता है - मार्क रोसिनोविच द्वारा प्रोसेस एक्सप्लोरर की तरह। इस लेख में, मैं संक्षेप में विंडोज 10 टास्क

  1. Google इमेज सर्च को प्रो की तरह कैसे इस्तेमाल करें

    वॉलपेपर से लेकर ट्रेंडी फैशनेबल परिधानों तक लगभग कुछ भी खोजने के लिए, Google हमारा निरंतर खोज इंजन है। कुछ ही सेकंड में, हमें अपनी खोज क्वेरी से संबंधित हजारों परिणाम मिलते हैं। Google से बेहतर कोई या कोई जगह नहीं है—वास्तव में। क्या आप जानते हैं कि आप फ़ाइल प्रकार, रंग, छवि आकार के आधार पर अपने ख