Kako biste sami implementirali arhitektonski pristup MVVM?
sobes.tech АИ
Одговор од АИ
MVVM (Model-View-ViewModel) je arhitektonski obrazac koji razdvaja UI, logiku prikaza i poslovnu logiku.
Glavne komponente:
- Model: Predstavlja podatke i poslovnu logiku. Ne zavisi od UI.
- View: UI sloj. Prikazuje podatke iz ViewModel-a i šalje akcije korisnika (događaje) u ViewModel. Ne sadrži poslovnu logiku.
- ViewModel: Sadrži logiku prikaza, priprema podatke iz Model-a za prikaz u View i obrađuje akcije korisnika. Nema direktne veze sa View, komunicira putem posmatranih podataka (Observable streams).
Samostalna implementacija:
-
Kreiranje Model-a: Jednostavni Plain Old Java Objects (POJO) ili Kotlin data klase za predstavljanje podataka, repozitoriji za pristup izvorima podataka (mreža, baza podataka).
// Primer Model-a data class User(val id: Int, val name: String, val email: String) class UserRepository { fun getUser(userId: Int): User { // Logika za dobijanje korisnika iz izvora podataka return User(userId, "Test User $userId", "test$userId@example.com") } } -
Kreiranje ViewModel-a: Klasa koja nasleđuje od
ViewModeliz Android Architecture Components (ili sopstvena implementacija sa Lifecycle awareness). ČuvaLiveDataili KotlinStateFlow/SharedFlowza posmatrane podatke. Sadrži metode za obradu akcija korisnika i ažuriranje podataka.// Primer ViewModel-a class UserViewModel(private val userRepository: UserRepository) : androidx.lifecycle.ViewModel() { private val _user = MutableLiveData<User>() val user: LiveData<User> = _user fun loadUser(userId: Int) { // U pravoj aplikaciji - asinhrono učitavanje val loadedUser = userRepository.getUser(userId) _user.value = loadedUser // Ažuriranje LiveData } fun updateUser(newUser: User) { // Logika za ažuriranje korisnika _user.value = newUser } } -
Implementacija View: Activity ili Fragment. Povezuje se sa ViewModel-om, pretplaćuje se na posmatrane podatke iz ViewModel-a, ažurira UI pri promeni podataka. Delegira obradu događaja korisnika (klikovi, unos teksta) u ViewModel. Koristi Data Binding ili View Binding za deklarativniju vezu.
// Primer 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) // Dobijanje ViewModel-a, po želji putem ViewModelProvider viewModel = ViewModelProvider(this).get(UserViewModel::class.java) // Pretplata na posmatrane podatke viewModel.user.observe(viewLifecycleOwner) { user -> // Ažuriranje UI pri promeni korisnika binding.userNameTextView.text = user.name binding.userEmailTextView.text = user.email } // Delegiranje događaja u ViewModel binding.loadUserButton.setOnClickListener { viewModel.loadUser(1) // Primer: učitavanje korisnika sa ID 1 } } override fun onDestroyView() { super.onDestroyView() _binding = null } } -
Povezivanje komponenti: View kreira instancu ViewModel-a (kroz
ViewModelProvider) i pretplaćuje se na njena posmatrana stanja. ViewModel radi sa Model-om.
Ključni aspekti samostalne implementacije:
- Korišćenje
LiveDataili Flow za reaktivnost i automatsko osvežavanje UI pri promeni podataka. - Korišćenje
ViewModelProviderza obezbeđivanje ispravnog životnog ciklusa ViewModel-a. - Korišćenje Dependency Injection (npr. Hilt ili Koin) za obezbeđivanje zavisnosti (npr. UserRepository) u ViewModel.
- Obrada asinhronih operacija (mrežni zahtevi, rad sa bazom podataka) u ViewModel-u koristeći korutine ili druge mehanizme.
Prednosti takvog pristupa:
- Testabilnost: ViewModel se lako može testirati odvojeno od UI.
- Razdvajanje odgovornosti: Jasno razdvajanje između UI, logike prikaza i poslovne logike.
- Otpornost na promene konfiguracije: ViewModel se čuva pri rotaciji ekrana i drugim promenama.
- Poboljšana održivost koda.