🤖
Android Tips
  • 🤖AOSP
    • Clone AOSP repository
    • Directory Structure
    • Setup IDE
      • Setup VSCode
    • Build
      • BluePrint for Application Project
      • BluePrint for Android Library Project
    • Manifest
      • sharedUserId
      • persistant
  • Gradle
    • Create Custom Build Config Variables
    • Create Custom manifest Variables
    • Make app debugable
  • Android Process
    • Find a process by name
    • Kill a process by Id
  • Catch any exception in Android
  • 🎨Theming
    • Theming
      • RRO
        • RRO Internals
        • RRO classes in AOSP
        • RRO Example
        • RRO Permission
      • Fabricated RRO (FRRO)
        • FRRO Example
        • Permission
  • Lifecycle
    • Basics
      • Lifecycle
        • Activity
        • Fragment
          • Fragment add
    • Lifecycle Aware Custom Class
  • ℹ️Interview
    • Interview Questions
    • Architecture Pattern
      • MVC Architecture pattern
      • MVP Architecture Pattern
      • MVVM Architecture Pattern
  • ↔️AIDL
    • Simple AIDL Communication
      • Creating an AIDL file
      • Create an AIDL server
      • Create AIDL client
      • Limitations
    • AIDL with callback
      • Create AILD interfaces
      • Create an AIDL server
      • Create AIDL client
Powered by GitBook
On this page
  • Class Diagram:
  • Code:
  1. Interview
  2. Architecture Pattern

MVVM Architecture Pattern

MVVM is an architectural pattern that separates the user interface development from the business logic and data model. It was introduced by Microsoft architects to simplify event-driven programming of user interfaces.

Core Components:

  1. Model

    • Represents the data and business logic

    • Contains the application's data and rules

    • Independent of the user interface

    • Manages data operations, storage, and retrieval

    • Typically includes data models, network calls, and data manipulation logic

  2. View

    • Represents the user interface

    • Displays data to the user

    • Handles user interactions

    • Observes changes in the ViewModel

    • Passive and doesn't contain complex logic

  3. ViewModel

    • Acts as a bridge between Model and View

    • Transforms Model data for display

    • Handles UI-related logic

    • Exposes data and commands to the View

    • Contains presentation logic

    • Uses data binding to update the View

Key Characteristics:

  • Data Binding: Automatically synchronizes data between View and ViewModel

  • Reactive Programming: Often uses observables and reactive streams

  • Separation of Concerns: Clear separation of UI, logic, and data layers

  • Testability: Easy to unit test due to clear component responsibilities

How MVVM Works:

  1. User interacts with the View

  2. View sends the action to ViewModel

  3. ViewModel processes the action

  4. ViewModel interacts with the Model to fetch/update data

  5. Model returns data to ViewModel

  6. ViewModel transforms and prepares data

  7. View is automatically updated through data binding

Advantages:

  • Improved separation of concerns

  • Enhanced testability

  • Easier maintenance

  • Supports complex user interfaces

  • Facilitates parallel development

  • Reduces boilerplate code

  • Supports reactive programming paradigms

Class Diagram:

Code:

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.runBlocking

// Data Model
data class User(
    val id: String,
    val name: String,
    val email: String
)

// Model Interface
interface UserModel {
    fun fetchUsers(): List<User>
    fun addUser(user: User)
    fun deleteUser(userId: String)
    fun observeDataChanges(): Flow<List<User>>
}

// View Interface
interface UserView {
    fun render(users: List<User>)
    fun showError(message: String)
    fun handleUserInteraction()
}

// ViewModel Interface
interface UserViewModel {
    val usersState: StateFlow<List<User>>
    fun loadUsers()
    fun addNewUser(name: String, email: String)
    fun deleteUser(userId: String)
}

// Concrete Model Implementation
class InMemoryUserModel : UserModel {
    private val users = mutableListOf(
        User("1", "John Doe", "john@example.com"),
        User("2", "Jane Smith", "jane@example.com")
    )

    override fun fetchUsers(): List<User> = users.toList()

    override fun addUser(user: User) {
        users.add(user)
    }

    override fun deleteUser(userId: String) {
        users.removeIf { it.id == userId }
    }

    override fun observeDataChanges(): Flow<List<User>> {
        // In a real-world scenario, this would be a more complex observable mechanism
        return MutableStateFlow(users)
    }
}

// Concrete ViewModel Implementation
class UserManagementViewModel(private val model: UserModel) : UserViewModel {
    private val _usersState = MutableStateFlow<List<User>>(emptyList())
    override val usersState: StateFlow<List<User>> = _usersState.asStateFlow()

    override fun loadUsers() {
        // In a real app, this would likely be an asynchronous operation
        val users = model.fetchUsers()
        _usersState.value = users
    }

    override fun addNewUser(name: String, email: String) {
        val newUser = User(
            id = (usersState.value.size + 1).toString(),
            name = name,
            email = email
        )
        model.addUser(newUser)
        _usersState.update { currentUsers -> currentUsers + newUser }
    }

    override fun deleteUser(userId: String) {
        model.deleteUser(userId)
        _usersState.update { currentUsers -> 
            currentUsers.filter { it.id != userId }
        }
    }
}

// Concrete View Implementation (Console-based for demonstration)
class ConsoleUserView(private val viewModel: UserViewModel) : UserView {
    override fun render(users: List<User>) {
        println("\n--- Current Users ---")
        users.forEach { user ->
            println("ID: ${user.id}, Name: ${user.name}, Email: ${user.email}")
        }
    }

    override fun showError(message: String) {
        println("Error: $message")
    }

    override fun handleUserInteraction() {
        while (true) {
            println("\nChoose an action:")
            println("1. View Users")
            println("2. Add User")
            println("3. Delete User")
            println("4. Exit")
            print("Enter your choice: ")

            when (readLine()?.trim()) {
                "1" -> {
                    // Render current users
                    render(viewModel.usersState.value)
                }
                "2" -> {
                    // Add user
                    print("Enter user name: ")
                    val name = readLine() ?: return
                    print("Enter user email: ")
                    val email = readLine() ?: return
                    viewModel.addNewUser(name, email)
                }
                "3" -> {
                    // Delete user
                    print("Enter user ID to delete: ")
                    val userId = readLine() ?: return
                    viewModel.deleteUser(userId)
                }
                "4" -> {
                    println("Exiting...")
                    return
                }
                else -> showError("Invalid choice")
            }
        }
    }
}

// MVVM Application Runner
class MVVMUserManagementApp {
    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            // Create MVVM components
            val model = InMemoryUserModel()
            val viewModel = UserManagementViewModel(model)
            val view = ConsoleUserView(viewModel)

            // Initial load of users
            viewModel.loadUsers()

            // Start user interaction
            view.handleUserInteraction()
        }
    }
}

// Bonus: Extension function to observe StateFlow (simulating reactive behavior)
fun <T> StateFlow<T>.observe(action: (T) -> Unit) {
    runBlocking {
        action(value)
    }
}
PreviousMVP Architecture PatternNextSimple AIDL Communication

Last updated 5 months ago

ℹ️