Sobes.tech
Junior

What are MV patterns?

sobes.tech AI

Answer from AI

MV patterns (Model-View-ViewModel, Model-View-Presenter, Model-View-Controller) are architectural patterns that separate the presentation (View), business logic (Model), and presentation logic (ViewModel/Presenter). The goal is to improve maintainability, testability, and scalability of the application by dividing responsibilities.

MVC (Model-View-Controller)

  • Model: Represents data and business logic.
  • View: Displays data from the Model.
  • Controller: Handles user actions, updates the Model, and selects the View for display.

In Android, View (activity/fragment) often combines functions of View and Controller, which complicates testing.

MVP (Model-View-Presenter)

  • Model: Represents data and business logic.
  • View: A passive interface that displays data passed by the Presenter and forwards user actions to it.
  • Presenter: Contains presentation logic, interacts with the Model, and updates the View via an interface.

Provides better separation of View and logic, making the Presenter more testable.

// Example of View interface in MVP
interface UserProfileView {
    fun showLoading()
    fun hideLoading()
    fun displayUserInfo(user: User)
    fun showError(message: String)
}

// Example of Presenter
class UserProfilePresenter(private val view: UserProfileView, private val repository: UserRepository) {
    fun loadUserProfile(userId: String) {
        view.showLoading()
        repository.getUser(userId) { user ->
            view.hideLoading()
            if (user != null) {
                view.displayUserInfo(user)
            } else {
                view.showError("Failed to load user")
            }
        }
    }
}

MVVM (Model-View-ViewModel)

  • Model: Represents data and business logic. Uses Observable to notify about changes.
  • View: Displays data from the ViewModel and sends user actions to it. Uses data binding to connect View and ViewModel.
  • ViewModel: Provides data for the View in a user-friendly format, contains presentation logic. Has no direct access to the View.

Uses observer mechanisms (LiveData, Flow) and data binding for automatic View updates when data in ViewModel changes. Makes the ViewModel completely independent of the Android framework and highly testable.

// Example ViewModel with LiveData
class UserProfileViewModel(private val repository: UserRepository) : ViewModel() {
    private val _user = MutableLiveData<User?>()
    val user: LiveData<User?> = _user

    private val _loading = MutableLiveData<Boolean>()
    val loading: LiveData<Boolean> = _loading

    private val _error = MutableLiveData<String?>()
    val error: LiveData<String?> = _error

    fun loadUserProfile(userId: String) {
        _loading.value = true
        repository.getUser(userId) { user ->
            _loading.value = false
            if (user != null) {
                _user.value = user
                _error.value = null
            } else {
                _user.value = null
                _error.value = "Failed to load user"
            }
        }
    }
}

Comparison:

Pattern Connection between View and Logic Testability of Logic Dependency of Logic on Android
MVC Tight (in Android, View often acts as Controller) Moderate High
MVP Loose (via View interface) High Low (Presenter does not depend on Android UI)
MVVM Loose (via observers and data binding) High Absent (ViewModel does not depend on Android UI)

The choice of pattern depends on project requirements and team preferences. Using MVVM with Android Jetpack components (ViewModel, LiveData, Data Binding) is the recommended approach in modern Android development.