Sobes.tech
Middle+

Ako by ste sami implementovali architektonický prístup MVVM?

sobes.tech AI

Odpoveď od AI

MVVM (Model-View-ViewModel) je architektonický vzor, ktorý rozdeľuje UI, logiku zobrazenia a biznis logiku.

Hlavné komponenty:

  • Model: Predstavuje dáta a biznis logiku. Nezávisí od UI.
  • View: UI vrstva. Zobrazuje dáta z ViewModel a odosiela akcie používateľa (události) do ViewModel. Neobsahuje biznis logiku.
  • ViewModel: Obsahuje logiku zobrazenia, pripravuje dáta z Modelu na zobrazenie vo View a spracováva akcie používateľa. Nemá priame odkazy na View, komunikuje cez pozorovateľné dáta (Observable streams).

Samostatná implementácia:

  1. Vytvorenie Modelu: Jednoduché Plain Old Java Objects (POJO) alebo Kotlin data triedy na reprezentáciu dát, repozitáre na prístup k zdrojom dát (sieť, databáza).

    // Príklad Modelu
    data class User(val id: Int, val name: String, val email: String)
    
    class UserRepository {
        fun getUser(userId: Int): User {
            // Logika na získanie používateľa zo zdroja dát
            return User(userId, "Test User $userId", "test$userId@example.com")
        }
    }
    
  2. Vytvorenie ViewModel: Trieda, ktorá dedí od ViewModel z Android Architecture Components (alebo vlastná implementácia s Lifecycle awareness). Uchováva LiveData alebo Kotlin StateFlow/SharedFlow na pozorovateľné dáta. Obsahuje metódy na spracovanie akcií používateľa a aktualizáciu dát.

    // Príklad ViewModel
    class UserViewModel(private val userRepository: UserRepository) : androidx.lifecycle.ViewModel() {
    
        private val _user = MutableLiveData<User>()
        val user: LiveData<User> = _user
    
        fun loadUser(userId: Int) {
            // V reálnej aplikácii - asynchrónne načítanie
            val loadedUser = userRepository.getUser(userId)
            _user.value = loadedUser // Aktualizácia LiveData
        }
    
        fun updateUser(newUser: User) {
            // Logika na aktualizáciu používateľa
            _user.value = newUser
        }
    }
    
  3. Implementácia View: Activity alebo Fragment. Spája sa s ViewModel, prihlasuje sa na pozorovateľné dáta z ViewModel, aktualizuje UI pri zmene dát. Deleguje spracovanie udalostí používateľa (kliknutia, zadávanie textu) do ViewModel. Používa Data Binding alebo View Binding pre deklaratívnejšie prepojenie.

    // Príklad View (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)
    
            // Získanie ViewModel, najlepšie cez ViewModelProvider
            viewModel = ViewModelProvider(this).get(UserViewModel::class.java)
    
            // Prihlásenie na pozorovateľné dáta
            viewModel.user.observe(viewLifecycleOwner) { user ->
                // Aktualizácia UI pri zmene používateľa
                binding.userNameTextView.text = user.name
                binding.userEmailTextView.text = user.email
            }
    
            // Delegovanie udalosti do ViewModel
            binding.loadUserButton.setOnClickListener {
                viewModel.loadUser(1) // Príklad: načítanie používateľa s ID 1
            }
        }
    
        override fun onDestroyView() {
            super.onDestroyView()
            _binding = null
        }
    }
    
  4. Prepojenie komponentov: View vytvára inštanciu ViewModel (cez ViewModelProvider) a prihlasuje sa na jej pozorovateľné dáta. ViewModel pracuje s Model.

Kľúčové aspekty samostatnej implementácie:

  • Použitie LiveData alebo Flow pre reaktivitu a automatické aktualizácie UI pri zmene dát.
  • Použitie ViewModelProvider na zabezpečenie správneho životného cyklu ViewModel.
  • Použitie Dependency Injection (napr. Hilt alebo Koin) na poskytovanie závislostí (napr. UserRepository) do ViewModel.
  • Spracovanie asynchrónnych operácií (sieťové požiadavky, práca s databázou) vo ViewModel s použitím korutín alebo iných mechanizmov.

Výhody takéhoto prístupu:

  • Testovateľnosť: ViewModel je možné ľahko otestovať samostatne od UI.
  • Rozdelenie zodpovedností: Jasné rozdelenie medzi UI, logikou zobrazenia a biznis logikou.
  • Odolnosť voči zmenám konfigurácie: ViewModel sa zachová pri otáčaní obrazovky a iných zmenách.
  • Vylepšená udržiavateľnosť kódu.