Introducció

L'arquitectura Model-View-ViewModel (MVVM) és un patró de disseny que separa la lògica de la interfície d'usuari (UI) de la lògica de negoci i de les dades. Això facilita la mantenibilitat, la testabilitat i la modularitat del codi. En aquest tema, aprendrem a implementar l'arquitectura MVVM en una aplicació Android utilitzant Android Jetpack.

Conceptes Clau

Model

  • Descripció: Representa les dades de l'aplicació i la lògica de negoci.
  • Funció: Gestiona les dades, ja sigui des d'una base de dades local o una API remota.

View

  • Descripció: Representa la interfície d'usuari.
  • Funció: Mostra les dades i rep les interaccions de l'usuari.

ViewModel

  • Descripció: Actua com a intermediari entre el Model i la View.
  • Funció: Proporciona dades a la View i gestiona la lògica de presentació.

Estructura del Projecte

Component Descripció
Model Conté les classes de dades i la lògica de negoci.
View Conté les activitats i fragments que mostren la interfície d'usuari.
ViewModel Conté les classes que gestionen la lògica de presentació i proporcionen dades a la View.

Implementació Pas a Pas

  1. Configuració del Projecte

Assegura't de tenir les següents dependències en el teu build.gradle:

dependencies {
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
    implementation "androidx.room:room-runtime:2.3.0"
    kapt "androidx.room:room-compiler:2.3.0"
}

  1. Creació del Model

Crea una classe de dades i una interfície DAO per gestionar les operacions de la base de dades.

// User.kt
@Entity(tableName = "users")
data class User(
    @PrimaryKey(autoGenerate = true) val id: Int,
    val name: String,
    val email: String
)

// UserDao.kt
@Dao
interface UserDao {
    @Query("SELECT * FROM users")
    fun getAllUsers(): LiveData<List<User>>

    @Insert
    suspend fun insert(user: User)
}

  1. Creació del ViewModel

Crea una classe ViewModel per gestionar la lògica de presentació.

// UserViewModel.kt
class UserViewModel(application: Application) : AndroidViewModel(application) {
    private val userDao: UserDao = AppDatabase.getDatabase(application).userDao()
    val allUsers: LiveData<List<User>> = userDao.getAllUsers()

    fun insert(user: User) = viewModelScope.launch {
        userDao.insert(user)
    }
}

  1. Creació de la View

Crea una activitat o fragment per mostrar la interfície d'usuari.

// MainActivity.kt
class MainActivity : AppCompatActivity() {
    private lateinit var userViewModel: UserViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        userViewModel = ViewModelProvider(this).get(UserViewModel::class.java)

        val userAdapter = UserAdapter()
        recyclerView.adapter = userAdapter

        userViewModel.allUsers.observe(this, Observer { users ->
            users?.let { userAdapter.submitList(it) }
        })

        addButton.setOnClickListener {
            val user = User(name = "John Doe", email = "[email protected]")
            userViewModel.insert(user)
        }
    }
}

  1. Creació del Layout

Defineix el layout XML per la teva activitat o fragment.

<!-- activity_main.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/addButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Add User" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

Exercici Pràctic

Objectiu

Implementar una aplicació senzilla que utilitzi l'arquitectura MVVM per gestionar una llista de tasques.

Passos

  1. Crea una classe Task amb els camps id, title i description.
  2. Defineix una interfície TaskDao amb les operacions CRUD.
  3. Implementa un TaskViewModel per gestionar les dades de les tasques.
  4. Crea una activitat TaskActivity per mostrar la llista de tasques i afegir-ne de noves.
  5. Defineix el layout XML per TaskActivity.

Solució

// Task.kt
@Entity(tableName = "tasks")
data class Task(
    @PrimaryKey(autoGenerate = true) val id: Int,
    val title: String,
    val description: String
)

// TaskDao.kt
@Dao
interface TaskDao {
    @Query("SELECT * FROM tasks")
    fun getAllTasks(): LiveData<List<Task>>

    @Insert
    suspend fun insert(task: Task)
}

// TaskViewModel.kt
class TaskViewModel(application: Application) : AndroidViewModel(application) {
    private val taskDao: TaskDao = AppDatabase.getDatabase(application).taskDao()
    val allTasks: LiveData<List<Task>> = taskDao.getAllTasks()

    fun insert(task: Task) = viewModelScope.launch {
        taskDao.insert(task)
    }
}

// TaskActivity.kt
class TaskActivity : AppCompatActivity() {
    private lateinit var taskViewModel: TaskViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_task)

        taskViewModel = ViewModelProvider(this).get(TaskViewModel::class.java)

        val taskAdapter = TaskAdapter()
        recyclerView.adapter = taskAdapter

        taskViewModel.allTasks.observe(this, Observer { tasks ->
            tasks?.let { taskAdapter.submitList(it) }
        })

        addButton.setOnClickListener {
            val task = Task(title = "New Task", description = "Task Description")
            taskViewModel.insert(task)
        }
    }
}

// activity_task.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/addButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Add Task" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

Conclusió

En aquest tema, hem après a implementar l'arquitectura MVVM en una aplicació Android. Hem separat la lògica de la interfície d'usuari de la lògica de negoci i de les dades, facilitant així la mantenibilitat i la testabilitat del codi. Aquesta estructura modular ens permet desenvolupar aplicacions més robustes i escalables.

© Copyright 2024. Tots els drets reservats