Jak byste sami implementovali architektonický přístup MVVM?
sobes.tech AI
Odpověď od AI
MVVM (Model-View-ViewModel) je vzor architektury, ktorý rozdeľuje UI, logiku prezentácie a podnikateľskú logiku.
Hlavné komponenty:
- Model: Predstavuje údaje a podnikateľskú logiku. Nezávisí od UI.
- View: Vrstva UI. Zobrazuje údaje z ViewModel a odosiela akcie používateľa (udalosť) do ViewModel. Neobsahuje podnikateľskú logiku.
- ViewModel: Obsahuje logiku prezentácie, pripravuje údaje z Modelu na zobrazenie vo View a spracováva akcie používateľa. Nemá priame odkazy na View, komunikuje cez sledovateľné údaje (Observable streams).
Samostatná implementácia:
-
Vytvorenie Modelu: Jednoduché objekty Java POJO alebo Kotlin data classes na reprezentáciu údajov, repozitáre na prístup k zdrojom údajov (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 získania používateľa zo zdroja údajov return User(userId, "Test User $userId", "test$userId@example.com") } } -
Vytvorenie ViewModel: Trieda, ktorá dedí od
ViewModelz Android Architecture Components (alebo vlastná implementácia s awareness o životnom cykle). UchovávaLiveDataalebo KotlinStateFlow/SharedFlowpre sledovateľné údaje. Obsahuje metódy na spracovanie akcií používateľa a aktualizáciu údajov.// 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 aktualizácie používateľa _user.value = newUser } } -
Implementácia View: Activity alebo Fragment. Spája sa s ViewModel, prihlasuje sa na sledovateľné údaje z ViewModel a aktualizuje UI pri zmene údajov. 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 sledovateľné údaje viewModel.user.observe(viewLifecycleOwner) { user -> // Aktualizácia UI 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 } } -
Prepojenie komponentov: View vytvára inštanciu ViewModel (cez
ViewModelProvider) a prihlasuje sa na jej sledovateľné údaje. ViewModel pracuje s Modelom.
Kľúčové aspekty samostatnej implementácie:
- Použitie
LiveDataalebo Flow pre reaktivitu a automatickú aktualizáciu UI pri zmene údajov. - Použitie
ViewModelProviderna zabezpečenie správneho životného cyklu ViewModel. - Použitie Dependency Injection (napríklad Hilt alebo Koin) na poskytovanie závislostí (napríklad UserRepository) do ViewModel.
- Spracovanie asynchrónnych operácií (žiadosti na sieť, 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 prezentácie a podnikateľskou logikou.
- Odolnosť voči zmenám konfigurácie: ViewModel sa zachová pri otáčaní obrazovky a iných zmenách konfigurácie.
- Vylepšená udržiavateľnosť kódu.