Sobes.tech
Middle+

Kendi başınıza MVVM mimari yaklaşımını nasıl uygularsınız?

sobes.tech yapay zeka

AI'dan gelen yanıt

MVVM (Model-View-ViewModel) bir mimarî desenidir ve kullanıcı arayüzü, sunum mantığı ve iş mantığını ayırır.

Ana bileşenler:

  • Model: Verileri ve iş mantığını temsil eder. UI'den bağımsızdır.
  • View: UI katmanı. ViewModel'den gelen verileri gösterir ve kullanıcı eylemlerini (olaylar) ViewModel'e gönderir. İş mantığını içermez.
  • ViewModel: Sunum mantığını içerir, Model'den alınan verileri View'da gösterilmek üzere hazırlar ve kullanıcı eylemlerini işler. Doğrudan View'e bağlı değildir, gözlemlenebilir veriler (Observable streams) aracılığıyla etkileşim kurar.

Bağımsız uygulama:

  1. Model oluşturma: Basit POJO nesneleri veya Kotlin veri sınıfları, veri erişimi için repository'ler (ağ, veritabanı).

    // Model örneği
    data class User(val id: Int, val name: String, val email: String)
    
    class UserRepository {
        fun getUser(userId: Int): User {
            // Veri kaynağından kullanıcıyı alma mantığı
            return User(userId, "Test Kullanıcı $userId", "test$userId@example.com")
        }
    }
    
  2. ViewModel oluşturma: Android Architecture Components'ten ViewModel'den türeyen sınıf (veya Lifecycle farkındalığı olan kendi uygulamanız). Gözlemlenebilir veriler için LiveData veya Kotlin StateFlow/SharedFlow tutar. Kullanıcı eylemlerini işlemek ve verileri güncellemek için metodlar içerir.

    // ViewModel örneği
    class UserViewModel(private val userRepository: UserRepository) : androidx.lifecycle.ViewModel() {
    
        private val _user = MutableLiveData<User>()
        val user: LiveData<User> = _user
    
        fun loadUser(userId: Int) {
            // Gerçek uygulamada asenkron yükleme
            val loadedUser = userRepository.getUser(userId)
            _user.value = loadedUser // LiveData'yı güncelle
        }
    
        fun updateUser(newUser: User) {
            // Kullanıcıyı güncelleme mantığı
            _user.value = newUser
        }
    }
    
  3. View uygulaması: Activity veya Fragment. ViewModel ile bağlanır, ViewModel'den gözlemlenebilir verilere abone olur, veriler değiştikçe UI'yi günceller. Kullanıcı olaylarını (tıklamalar, metin girişi) ViewModel'e devreder. Daha deklaratif bağlama için Data Binding veya View Binding kullanır.

    // View (Fragment) örneği
    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'ı edin, tercihen ViewModelProvider aracılığıyla
            viewModel = ViewModelProvider(this).get(UserViewModel::class.java)
    
            // Gözlemlenebilir verilere abone ol
            viewModel.user.observe(viewLifecycleOwner) { user ->
                // Kullanıcı değiştiğinde UI'yi güncelle
                binding.userNameTextView.text = user.name
                binding.userEmailTextView.text = user.email
            }
    
            // Olayı ViewModel'e devret
            binding.loadUserButton.setOnClickListener {
                viewModel.loadUser(1) // Örnek: ID 1 olan kullanıcıyı yükle
            }
        }
    
        override fun onDestroyView() {
            super.onDestroyView()
            _binding = null
        }
    }
    
  4. Bileşenleri bağlama: View, ViewModel örneği oluşturur (ViewModelProvider aracılığıyla) ve gözlemlenebilir verilere abone olur. ViewModel, Model ile çalışır.

Bağımsız uygulamanın temel noktaları:

  • LiveData veya Flow kullanımıyla reaktivite ve veriler değiştiğinde otomatik UI güncellemesi
  • ViewModelProvider kullanımıyla ViewModel'in doğru yaşam döngüsünün sağlanması
  • Dependency Injection (örneğin Hilt veya Koin) kullanımıyla bağımlılıkların (örneğin UserRepository) ViewModel'e sağlanması
  • Ağ istekleri, veritabanı işlemleri gibi asenkron işlemlerin ViewModel'de coroutine veya diğer mekanizmalarla yönetilmesi

Bu yaklaşımın avantajları:

  • Test edilebilirlik: ViewModel, UI'den bağımsız olarak kolayca test edilebilir
  • Sorumlulukların ayrılması: UI, sunum mantığı ve iş mantığı arasında net ayrım
  • Konfigürasyon değişikliklerine dayanıklılık: ViewModel, ekran döndürmeleri ve diğer konfigürasyon değişiklikleri sırasında korunur
  • Kodun bakımını kolaylaştırır.