Sobes.tech
Middle+

Ինչպե՞ս եք ինքնուրույն իրականացնում MVVM ճարտարապետական մոտեցումը։

sobes.tech AI

Պատասխան AI-ից

MVVM (Մոդել-Դիտակ-Դիտակմոդել) — դա ճարտարապետական ձևանմուշ է, որը բաժանում է UI-ն, ներկայացման տրամաբանությունը և բիզնես տրամաբանությունը:

Հիմնական բաղադրիչները՝

  • Model: Ներկայացնում է տվյալները և բիզնես տրամաբանությունը: Անկախ է UI-ից:
  • View: UI շերտը: Ներկայացնում է ViewModel-ից տվյալները և ուղարկում օգտագործողի գործողությունները (հետադարձ կապեր) ViewModel-ին: Չի պարունակում բիզնես տրամաբանություն:
  • ViewModel: Ներկայացման տրամաբանությունը պարունակում է, պատրաստում է Model-ից տվյալները ցուցադրման համար և մշակում է օգտագործողի գործողությունները: Չի ունի ուղիղ կապ View-ի հետ, փոխազդեցությունը կատարվում է դիտվող տվյալների (Observable streams) միջոցով:

Անհատական իրականացման քայլեր՝

  1. Model-ի ստեղծում: Պարզ Plain Old Java Objects (POJO) կամ Kotlin data դասեր տվյալների ներկայացման համար, պահեստայիններ՝ տվյալների աղբյուրներին մուտք գործելու համար (միացում, տվյալների բազա):

    // Model-ի օրինակ
    data class User(val id: Int, val name: String, val email: String)
    
    class UserRepository {
        fun getUser(userId: Int): User {
            // Տվյալների աղբյուրից օգտվողի ստացում
            return User(userId, "Test User $userId", "test$userId@example.com")
        }
    }
    
  2. ViewModel-ի ստեղծում: Կլաս, որը ժառանգում է ViewModel-ից Android Architecture Components-ից (կամ սեփական իրականացում՝ Lifecycle գիտակցությամբ): Պահպանում է LiveData կամ Kotlin StateFlow/SharedFlow-ը դիտվող տվյալների համար: Ունեցում է մեթոդներ օգտագործողի գործողությունները մշակելու և տվյալները թարմացնելու համար:

    // ViewModel-ի օրինակ
    class UserViewModel(private val userRepository: UserRepository) : androidx.lifecycle.ViewModel() {
    
        private val _user = MutableLiveData<User>()
        val user: LiveData<User> = _user
    
        fun loadUser(userId: Int) {
            // Իրական ծրագրում՝ ասինխրոն բեռնում
            val loadedUser = userRepository.getUser(userId)
            _user.value = loadedUser // LiveData-ի թարմացում
        }
    
        fun updateUser(newUser: User) {
            // Օգտվողի թարմացման տրամաբանություն
            _user.value = newUser
        }
    }
    
  3. Դիտակմոդելի իրականացում: Activity կամ Fragment: Կապվում է ViewModel-ի հետ, բաժանորդագրվում է ViewModel-ի դիտվող տվյալներին, թարմացնում UI-ն տվյալների փոփոխության դեպքում: Օգտագործում է Data Binding կամ View Binding՝ ավելի դեկլարատիվ կապի համար:

    // Դիտակի օրինակ (Fragment)
    class UserFragment : Fragment() {
    
        private lateinit var viewModel: UserViewModel
        private var _binding: FragmentUserBinding? = null
        private val binding get() = _binding!!
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View {
            _binding = FragmentUserBinding.inflate(inflater, container, false)
            return binding.root
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
    
            // ViewModel-ի ստացում՝ լավագույնը ViewModelProvider-ով
            viewModel = ViewModelProvider(this).get(UserViewModel::class.java)
    
            // Դիտվող տվյալների բաժանորդագրություն
            viewModel.user.observe(viewLifecycleOwner) { user ->
                // UI-ի թարմացում տվյալների փոփոխության դեպքում
                binding.userNameTextView.text = user.name
                binding.userEmailTextView.text = user.email
            }
    
            // իրադարձության փոխանցում ViewModel-ին
            binding.loadUserButton.setOnClickListener {
                viewModel.loadUser(1) // Օրինակ՝ օգտվողի բեռնում ID-ով 1
            }
        }
    
        override fun onDestroyView() {
            super.onDestroyView()
            _binding = null
        }
    }
    
  4. Բաղադրիչների կապը: View-ը ստեղծում է ViewModel-ի օրինակ (ViewModelProvider-ով) և բաժանորդագրվում է նրա դիտվող տվյալներին: ViewModel-ը աշխատում է Model-ի հետ:

Հիմնարար սկզբունքներ՝

  • Օգտագործել LiveData կամ Flow՝ ռեակտիվության և ավտոմատ UI թարմացման համար տվյալների փոփոխության դեպքում:
  • Օգտագործել ViewModelProvider՝ ViewModel-ի ճիշտ կյանքի ցիկլի ապահովման համար:
  • Օգտագործել Dependency Injection (օրինակ՝ Hilt կամ Koin)՝ կախվածությունները (օրինակ՝ UserRepository) տրամադրելու համար ViewModel-ին:
  • Աշխատել ասինխրոն գործողությունների հետ (միջանցքային հարցումներ, տվյալների բազայի աշխատանք)՝ ViewModel-ում՝ օգտագործելով կուրիններ կամ այլ մեխանիզմներ:

Առավելություններ՝

  • Թեստավորման հեշտություն: ViewModel-ը հեշտ է թեստել առանձին UI-ից:
  • Պատասխանատվության բաժանում: Հստակ բաժանում UI-ի, ներկայացման տրամաբանության և բիզնես տրամաբանության միջև:
  • Կոնֆիգուրացիայի փոփոխությունների դիմաց կայունություն: ViewModel-ը պահվում է էկրանի շրջադարձի և այլ փոփոխությունների ժամանակ:
  • Կոդի բարելավված պահպանելիություն: