Sobes.tech
Junior

Opowiedz o wzorcu MVVM.

sobes.tech AI

Odpowiedź od AI

Model-Widok-Model Widok (MVVM) to wzorzec architektoniczny, który oddziela interfejs użytkownika (Widok) od logiki biznesowej (Model) za pomocą pośrednika — Model Widoku (ViewModel).

  • Model: Reprezentuje dane i logikę biznesową aplikacji. Nie zawiera żadnej logiki specyficznej dla UI.
  • Widok: Wyświetla dane z ViewModel i wysyła akcje użytkownika (np. naciśnięcia przycisków) do ViewModel. Nie zawiera logiki biznesowej, tylko logikę prezentacji.
  • ViewModel: Działa jako łącznik. Udostępnia dane z Modelu w formacie przyjaznym do wyświetlenia i obsługuje żądania od Widoku, aktualizując Model. Zawiera logikę prezentacji, ale nie manipuluje bezpośrednio Widokiem. Często używa LiveData lub StateFlow do reaktywnych aktualizacji Widoku.

Zalety:

  • Podział odpowiedzialności: Poprawia czytelność i łatwość utrzymania kodu.
  • Testowalność: ViewModel jest łatwy do testowania w izolacji, ponieważ nie zależy od API Androida.
  • Wsparcie dla trwałości: ViewModel przetrwa zmiany konfiguracji (np. obrót ekranu) i unika ponownego pobierania danych.
  • Lepsza modularność.

Przykład struktury:

// Model (repozytorium dla przykładu)
class UserRepository {
    fun getUsers(): List<User> {
        // ... logika pobierania użytkowników ...
        return listOf(User("Alice"), User("Bob"))
    }
}

// ViewModel
class UserViewModel(private val repository: UserRepository) : ViewModel() {
    private val _users = MutableLiveData<List<User>>()
    val users: LiveData<List<User>> = _users

    init {
        loadUsers()
    }

    private fun loadUsers() {
        _users.value = repository.getUsers()
    }
}

// Widok (Fragment/Activity)
class UserFragment : Fragment() {
    private val viewModel: UserViewModel by viewModels() // Użycie delegata od Android KTX

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        viewModel.users.observe(viewLifecycleOwner) { userList ->
            // Aktualizacja UI (np. adapter RecyclerView)
            updateUI(userList)
        }
    }

    private fun updateUI(userList: List<User>) {
        // Logika aktualizacji TextView, RecyclerView itp.
    }
}