¿Cómo crear una aplicación de Android de notas simples usando MVVM y la base de datos de habitaciones?

Android nos proporciona una característica con la que podemos almacenar los datos de los usuarios dentro de su propio móvil con diferentes opciones de almacenamiento como Preferencias Compartidas , base de datos SQLite y la Base de Datos de Salas . Todas las técnicas de almacenamiento de datos tienen diferentes casos de uso. En este artículo, analizaremos específicamente el uso de una base de datos de habitaciones con componentes de arquitectura en Android. En este artículo, analizaremos específicamente componentes como LiveData, ViewModel y Room. Podemos llegar a ver la explicación de cada componente en detalle. A continuación se muestra la guía para ello. 

Los componentes que usaremos dentro de la aplicación se enumeran a continuación con una explicación detallada: 

  • LiveData : Live Data es una clase de titular de datos que se puede observar. Mantiene y almacena en caché la última versión de los datos y notifica a nuestro observador cada vez que los datos se actualizan o modifican. Live Data gestiona todo esto automáticamente, ya que está al tanto de los cambios de estado relevantes del ciclo de vida mientras observa.
  • ViewModel : View Modal actúa como un centro de comunicación entre el repositorio y la interfaz de usuario. La interfaz de usuario ya no necesita preocuparse por el origen de los datos. Las instancias de ViewModel sobreviven a la recreación de Actividad/Fragmento.
  • Repositorio : Repositorio es una clase que se utiliza principalmente para administrar múltiples fuentes de datos.
  • Entidad : Entidad es una clase anotada que se usa para describir una tabla de base de datos cuando estamos trabajando con Room.
  • Room Database : Room Database es una versión improvisada de SQLite Database. Simplifica el trabajo de la base de datos y sirve como punto de acceso a la base de datos SQLite subyacente. La sala usa DAO para emitir consultas a la base de datos SQLite.
  • DAO : DAO es un objeto de acceso a datos que se utiliza para asignar consultas SQL a funciones.

¿Qué vamos a construir en este artículo? 

Construiremos una aplicación de notas simple en la que mostraremos la lista de notas en Recycler View que agrega el usuario. Junto con eso, también podremos agregar una nueva nota a su aplicación. Usaremos Room Database para almacenar datos en los dispositivos de los usuarios. A continuación se muestra el video en el que veremos lo que vamos a construir en este artículo.

Implementación paso a paso

Paso 1: Crear un nuevo proyecto

Para crear un nuevo proyecto en Android Studio, consulte Cómo crear/iniciar un nuevo proyecto en Android Studio . Tenga en cuenta que seleccione Kotlin como lenguaje de programación.

Paso 2: Actualización del archivo build.gradle (proyecto). 

Vaya a la aplicación > Gradle Scripts > archivo de nivel build.gradle(:project) y dentro de este archivo, tenemos que agregar el siguiente código en ese archivo que se usará para nuestras versiones de dependencias. Así que tenemos que agregar el siguiente bloque de código en el último de este archivo. 

ext {
    activityVersion = '1.2.3'
    appCompatVersion = '1.3.0'
    constraintLayoutVersion = '2.0.4'
    coreTestingVersion = '2.1.0'
    coroutines = '1.5.0'
    lifecycleVersion = '2.3.1'
    materialVersion = '1.3.0'
    roomVersion = '2.3.0'
    // testing
    junitVersion = '4.13.2'
    espressoVersion = '3.1.0'
    androidxJunitVersion = '1.1.2'
}  

Paso 3: Actualiza tu archivo build.gradle (:app)

Navegue a la aplicación> build.gradle y dentro de eso, en la primera sección de complementos, tenemos que agregar la identificación para un complemento más. A continuación se muestra el código de todos los complementos que están presentes dentro de nuestro build.gradle.

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    // add below plugin
    id 'kotlin-kapt'
}

Ahora, dentro de la sección de Android en el mismo archivo, tenemos que agregar el siguiente bloque en la última parte de la sección de Android. A continuación se muestra el código para ese bloque. 

packagingOptions {
    exclude 'META-INF/atomicfu.kotlin_module'
}

Ahora agregue las siguientes dependencias dentro de su archivo build.gradle. Simplemente tenemos que actualizar la sección de dependencias con la siguiente. 

dependencies {
    implementation "androidx.appcompat:appcompat:$rootProject.appCompatVersion"
    implementation "androidx.activity:activity-ktx:$rootProject.activityVersion"

    // Dependencies for working with Architecture components
    // You'll probably have to update the version numbers in build.gradle (Project)

    // Room components
    implementation "androidx.room:room-ktx:$rootProject.roomVersion"
    kapt "androidx.room:room-compiler:$rootProject.roomVersion"
    androidTestImplementation "androidx.room:room-testing:$rootProject.roomVersion"

    // Lifecycle components
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$rootProject.lifecycleVersion"
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$rootProject.lifecycleVersion"
    implementation "androidx.lifecycle:lifecycle-common-java8:$rootProject.lifecycleVersion"

    // Kotlin components
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$rootProject.coroutines"
    api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$rootProject.coroutines"

    // UI
    implementation "androidx.constraintlayout:constraintlayout:$rootProject.constraintLayoutVersion"
    implementation "com.google.android.material:material:$rootProject.materialVersion"

    // Testing
    testImplementation "junit:junit:$rootProject.junitVersion"
    androidTestImplementation "androidx.arch.core:core-testing:$rootProject.coreTestingVersion"
    androidTestImplementation ("androidx.test.espresso:espresso-core:$rootProject.espressoVersion", {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    androidTestImplementation "androidx.test.ext:junit:$rootProject.androidxJunitVersion"
}

Después de actualizar su archivo gradle. Ahora tenemos que sincronizar su proyecto y luego tenemos que instalar todas las dependencias dentro de la aplicación haciendo clic en la opción sincronizar ahora en la esquina superior derecha. Después de instalar todas las dependencias dentro de nuestra aplicación, ahora nos moveremos para crear una Entidad para nuestra aplicación. 

Paso 4: agregar nuevos colores en el archivo colors.xml

Vaya a la aplicación > res > valores > colores.xml y agréguele los siguientes colores. 

XML

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="purple_200">#296D98</color>
    <color name="purple_500">#296D98</color>
    <color name="purple_700">#296D98</color>
    <color name="teal_200">#FF03DAC5</color>
    <color name="teal_700">#FF018786</color>
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>
  
    <color name="black_shade_1">#0e2433</color>
    <color name="black_shade_2">#1C4966</color>
    <color name="black_shade_3">#22252D</color>
    <color name="gray">#424242</color>
    <color name="yellow">#ffa500</color>
    <color name="dark_blue_shade">#0D2162</color>
    <color name="dark_blue_shade_2">#17388E</color>
    <color name="light_blue_shade">#12B2E6</color>
  
</resources>

Paso 5: Creando una Entidad

Una Entidad es básicamente una clase modal o una estructura de nuestra base de datos en la que seremos utilizados para crear una estructura de base de datos. Dentro de nuestra aplicación, tendremos una tabla simple que solo tendrá dos columnas, como ID y texto. ID se utilizará para la identificación de una entrada y el texto es la columna para la identificación de la columna de texto. A continuación se muestra la estructura de la tabla para nuestra base de datos. A continuación se muestra la imagen de la base de datos. 

Para crear una nueva Entidad, tenemos que crear una nueva clase de Kotlin. Para crear esto, simplemente tenemos que navegar hasta el nombre del paquete de su aplicación. Haga clic derecho en él, luego en nuevo y seleccione Kotlin File/Class y luego especifique el nombre de la clase como Nota y agregue el código a continuación. Se agregan comentarios en el código para conocer con más detalle. 

Kotlin

package com.gtappdevelopers.noteapplication
  
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
  
// on below line we are specifying our table name
@Entity(tableName = "notesTable")
  
// on below line we are specifying our column infor
// and inside that we are passing our column name
class Note (@ColumnInfo(name = "title")val noteTitle :String,@ColumnInfo(name = "description")val noteDescription :String,@ColumnInfo(name = "timestamp")val timeStamp :String) {
    // on below line we are specifying our key and 
    // then auto generate as true and we are 
    // specifying its initial value as 0
    @PrimaryKey(autoGenerate = true) var id = 0
}

 
Paso 6: Crear una clase DAO

DAO es un objeto de acceso a datos que se utiliza para especificar consultas SQL y luego asociarlas con diferentes llamadas a métodos. DAO puede ser una clase abstracta o una interfaz. Dentro de la clase DAO, tenemos que crear diferentes métodos, como insertar, eliminar los datos y leer los datos de nuestra base de datos. Entonces, esta clase básicamente interactuará con nuestra base de datos para agregar o eliminar datos dentro de nuestra base de datos.

Para crear una interfaz DAO, simplemente tenemos que navegar hasta el nombre del paquete de la aplicación, hacer clic con el botón derecho en él> Nuevo archivo Kotlin y tenemos que seleccionar como Interfaz y nombrarlo como NotesDao y tenemos que crear este archivo. Después de crear este archivo, debemos agregarle el siguiente código. 

Kotlin

package com.gtappdevelopers.noteapplication
  
import androidx.lifecycle.LiveData
import androidx.room.*
  
// annotation for dao class. 
@Dao
interface NotesDao {
  
    // below is the insert method for 
    // adding a new entry to our database. 
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun insert(note :Note)
  
    // below is the delete method
    // for deleting our note. 
    @Delete
    suspend fun delete(note: Note)
  
    // below is the method to read all the notes
    // from our database we have specified the query for it. 
    // inside the query we are arranging it in ascending
    // order on below line and we are specifying 
    // the table name from which 
    // we have to get the data. 
    @Query("Select * from notesTable order by id ASC")
    fun getAllNotes(): LiveData<List<Note>>
    
      // below method is use to update the note. 
      @Update
    suspend fun update(note: Note)
  
}

 
Paso 7: agregar una base de datos de habitaciones para nuestra aplicación

¿Qué es básicamente una base de datos de habitaciones?

  • Room es básicamente una capa de base de datos sobre la base de datos SQLite.
  • Room se ocupa de las tareas mundanas que solía manejar con SQLite Open Helper.
  • Room usa el DAO para emitir consultas a su base de datos.
  • Room proporciona verificaciones en tiempo de compilación de las declaraciones de SQLite.

Ahora, para almacenar datos dentro del dispositivo del usuario, debemos crear una base de datos Room para almacenar los datos. Entonces, para crear una base de datos, debemos crear una clase abstracta para crear nuestra base de datos. En esto, simplemente construiremos nuestra base de datos usando Room y especificaremos el nombre de nuestra base de datos. Para crear una nueva clase abstracta, debemos ir al nombre del paquete de la aplicación> hacer clic derecho en él> Nuevo> archivo Kotlin y lo llamamos NoteDatabase . Después de crear esta clase, debemos agregarle el siguiente código. Se agregan comentarios en el código para conocer con más detalle. 

Kotlin

package com.gtappdevelopers.noteapplication
  
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
  
@Database(entities = arrayOf(Note::class), version = 1, exportSchema = false)
abstract class NoteDatabase : RoomDatabase() {
  
    abstract fun getNotesDao(): NotesDao
  
    companion object {
        // Singleton prevents multiple 
        // instances of database opening at the
        // same time.
        @Volatile
        private var INSTANCE: NoteDatabase? = null
  
        fun getDatabase(context: Context): NoteDatabase {
            // if the INSTANCE is not null, then return it,
            // if it is, then create the database
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    NoteDatabase::class.java,
                    "note_database"
                ).build()
                INSTANCE = instance
                // return instance
                instance
            }
        }
    }
}

 
Paso 8: crear una clase de repositorio

La clase de repositorio básicamente abstrae el acceso a múltiples fuentes de datos, como obtener los datos de la API o obtener los datos de la base de datos de Room. Una clase de repositorio nos proporcionará una API limpia para acceder a los datos del resto de la aplicación. El repositorio contendrá una lógica que decidirá si tenemos que buscar los datos de la red o tenemos que obtener los datos de la base de datos. 

Creación de una clase de repositorio. Para crear un Repositorio, tenemos que crear un nuevo archivo Kotlin simplemente haciendo clic derecho en el nombre del paquete de su aplicación> Haga clic derecho en él> Nuevo> Clase Kotlin y especifique el nombre de la clase como NoteRepository y agregue el código a continuación. Se agregan comentarios en el código para conocer con más detalle. 

Kotlin

package com.gtappdevelopers.noteapplication
  
import androidx.annotation.WorkerThread
import androidx.lifecycle.LiveData
import java.util.concurrent.Flow
  
class NoteRepository(private val notesDao: NotesDao) {
      
    // on below line we are creating a variable for our list
    // and we are getting all the notes from our DAO class. 
    val allNotes: LiveData<List<Note>> = notesDao.getAllNotes()
      
    // on below line we are creating an insert method
    // for adding the note to our database. 
    suspend fun insert(note: Note) {
        notesDao.insert(note)
    }
      
    // on below line we are creating a delete method
    // for deleting our note from database. 
    suspend fun delete(note: Note){
        notesDao.delete(note)
    }
      
     // on below line we are creating a update method for
     // updating our note from database. 
     suspend fun update(note: Note){
        notesDao.update(note)
    }
}

 
Paso 9: crear un modelo de vista 

ViewModel se utiliza básicamente para proporcionar los datos a nuestra interfaz de usuario. Actúa como una capa de comunicación entre el repositorio y la interfaz de usuario. Podemos usar View Modal para compartir datos entre nuestros fragmentos. Para crear una vista modal, simplemente debemos crear una nueva clase de Kotlin y luego debemos nombrarla como NoteViewModal y agregarle el siguiente código. Se agregan comentarios en el código para conocer con más detalle. 

Kotlin

package com.gtappdevelopers.noteapplication
  
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
  
class NoteViewModal (application: Application) :AndroidViewModel(application) {
      
    // on below line we are creating a variable
    // for our all notes list and repository
    val allNotes : LiveData<List<Note>>
    val repository : NoteRepository
  
    // on below line we are initializing 
    // our dao, repository and all notes 
    init {
        val dao = NoteDatabase.getDatabase(application).getNotesDao()
        repository = NoteRepository(dao)
        allNotes = repository.allNotes
    }
  
    // on below line we are creating a new method for deleting a note. In this we are 
    // calling a delete method from our repository to delete our note. 
    fun deleteNote (note: Note) = viewModelScope.launch(Dispatchers.IO) {
        repository.delete(note)
    }
      
    // on below line we are creating a new method for updating a note. In this we are 
    // calling a update method from our repository to update our note. 
    fun updateNote(note: Note) = viewModelScope.launch(Dispatchers.IO) {
       repository.update(note)
    }
  
          
    // on below line we are creating a new method for adding a new note to our database 
    // we are calling a method from our repository to add a new note. 
    fun addNote(note: Note) = viewModelScope.launch(Dispatchers.IO) {
        repository.insert(note)
    }
}

 
Paso 10: trabajar con el archivo activity_main.xml 

Ahora trabajaremos en la parte de la interfaz de usuario de nuestra aplicación. Ahora tenemos que navegar a app > res > activity_main.xml y agregarle el siguiente código. Se agregan comentarios en el código para conocer con más detalle.

XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black_shade_1"
    tools:context=".MainActivity">
  
    <!--recycler view for displaying all notes-->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/notesRV"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="5dp"
        tools:listitem="@layout/note_rv_item" />
  
    <!--fab for adding a new note-->
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/idFAB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:layout_margin="20dp"
        android:src="@drawable/ic_add"
        app:backgroundTint="@color/black_shade_2"
        app:tint="@color/white" />
  
</RelativeLayout>

Paso 11: Creación de un nuevo archivo de diseño para nuestro elemento de RecyclerView 

Vaya a la aplicación > res > diseño > haga clic con el botón derecho en él > Nuevo > Archivo de recursos de diseño y nombre su archivo como note_rv_item y agréguele el siguiente código. Se agregan comentarios en el código para conocer con más detalle. 

XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp"
    app:cardBackgroundColor="@color/black_shade_2"
    app:cardCornerRadius="5dp"
    app:cardElevation="3dp">
  
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="4dp">
  
        <!--text view for displaying our note text-->
        <TextView
            android:id="@+id/idTVNote"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="3dp"
            android:layout_toLeftOf="@id/idIVDelete"
            android:padding="4dp"
            android:text="Note"
            android:textColor="@color/white"
            android:textSize="18sp" />
  
        <!--text view for displaying our last updated text-->
        <TextView
            android:id="@+id/idTVDate"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/idTVNote"
            android:layout_margin="3dp"
            android:layout_toLeftOf="@id/idIVDelete"
            android:padding="4dp"
            android:text="Updated At"
            android:textColor="@color/white"
            android:textSize="13sp" />
  
        <!--imageview for displaying delete icon-->
        <ImageView
            android:id="@+id/idIVDelete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_margin="3dp"
            android:padding="3dp"
            android:src="@drawable/ic_delete"
            app:tint="@color/white" />
  
    </RelativeLayout>
      
</androidx.cardview.widget.CardView>

Paso 12: crear una clase de adaptador

Ahora crearemos una clase de adaptador que se usará para configurar los datos en cada elemento de nuestra vista de reciclador. Para crear una clase de Adaptador, tenemos que navegar a la aplicación > Java > el nombre del paquete de su aplicación > Hacer clic con el botón derecho en él > Nuevo > Kotlin/Class y nombrarlo como NoteRVAdapter y agregarle el siguiente código. Se agregan comentarios en el código para conocer con más detalle. 

Kotlin

package com.gtappdevelopers.noteapplication
  
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
  
class NoteRVAdapter(
    val context: Context,
    val noteClickDeleteInterface: NoteClickDeleteInterface,
    val noteClickInterface: NoteClickInterface
) :
    RecyclerView.Adapter<NoteRVAdapter.ViewHolder>() {
  
    // on below line we are creating a 
    // variable for our all notes list.
    private val allNotes = ArrayList<Note>()
  
    // on below line we are creating a view holder class.
    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        // on below line we are creating an initializing all our 
        // variables which we have added in layout file.
        val noteTV = itemView.findViewById<TextView>(R.id.idTVNote)
        val dateTV = itemView.findViewById<TextView>(R.id.idTVDate)
        val deleteIV = itemView.findViewById<ImageView>(R.id.idIVDelete)
    }
  
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        // inflating our layout file for each item of recycler view.
        val itemView = LayoutInflater.from(parent.context).inflate(
            R.layout.note_rv_item,
            parent, false
        )
        return ViewHolder(itemView)
    }
  
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        // on below line we are setting data to item of recycler view.
        holder.noteTV.setText(allNotes.get(position).noteTitle)
        holder.dateTV.setText("Last Updated : " + allNotes.get(position).timeStamp)
        // on below line we are adding click listener to our delete image view icon.
        holder.deleteIV.setOnClickListener {
            // on below line we are calling a note click
            // interface and we are passing a position to it.
            noteClickDeleteInterface.onDeleteIconClick(allNotes.get(position))
        }
  
        // on below line we are adding click listener
        // to our recycler view item.
        holder.itemView.setOnClickListener {
            // on below line we are calling a note click interface
            // and we are passing a position to it.
            noteClickInterface.onNoteClick(allNotes.get(position))
        }
    }
  
    override fun getItemCount(): Int {
        // on below line we are 
        // returning our list size.
        return allNotes.size
    }
  
    // below method is use to update our list of notes.
    fun updateList(newList: List<Note>) {
        // on below line we are clearing 
        // our notes array list
        allNotes.clear()
        // on below line we are adding a 
        // new list to our all notes list.
        allNotes.addAll(newList)
        // on below line we are calling notify data 
        // change method to notify our adapter.
        notifyDataSetChanged()
    }
}
  
interface NoteClickDeleteInterface {
    // creating a method for click 
    // action on delete image view.
    fun onDeleteIconClick(note: Note)
}
  
interface NoteClickInterface {
    // creating a method for click action
    // on recycler view item for updating it.
    fun onNoteClick(note: Note)
}

 
Paso 13: crear una nueva actividad para agregar y editar una nota 

Vaya a la aplicación > java > el nombre del paquete de su aplicación > haga clic con el botón derecho en él > Nuevo > seleccione Actividad vacía y asígnele el nombre AddEditNoteActivity y cree una nueva actividad. Después de eso, navegue hasta el archivo app > res > layout > activity_add_edit_note.xml y agréguele el siguiente código. Se agregan comentarios en el código para conocer con más detalle.

XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black_shade_1"
    tools:context=".AddEditNoteActivity">
  
    <!--edit text for note title-->
    <EditText
        android:id="@+id/idEdtNoteName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:hint="Enter Note Title"
        android:textColor="@color/white"
        android:textColorHint="@color/white" />
      
    <!--edit text for note description-->
    <EditText
        android:id="@+id/idEdtNoteDesc"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/idBtn"
        android:layout_below="@id/idEdtNoteName"
        android:layout_margin="10dp"
        android:background="@color/black_shade_1"
        android:gravity="start|top"
        android:hint="Enter your Note Details"
        android:inputType="textMultiLine"
        android:singleLine="false"
        android:textColor="@color/white"
        android:textColorHint="@color/white" />
  
    <!--button for saving and updating a note-->
    <Button
        android:id="@+id/idBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_margin="20dp"
        android:background="@drawable/custom_button_back"
        android:text="Button"
        android:textAllCaps="false"
        android:textColor="@color/white" />
  
</RelativeLayout>

 
Paso 14: trabajar con el archivo MainActivity.kt

Vaya a la aplicación > java > el nombre del paquete de su aplicación > archivo MainActivity.kt y agréguele el siguiente código. Se agregan comentarios en el código para conocer con más detalle. 

Kotlin

package com.gtappdevelopers.noteapplication
  
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.floatingactionbutton.FloatingActionButton
import java.util.*
  
class MainActivity : AppCompatActivity(), NoteClickInterface, NoteClickDeleteInterface {
  
    // on below line we are creating a variable
    // for our recycler view, exit text, button and viewmodel.
    lateinit var viewModal: NoteViewModal
    lateinit var notesRV: RecyclerView
    lateinit var addFAB: FloatingActionButton
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
          
        // on below line we are initializing
        // all our variables.
        notesRV = findViewById(R.id.notesRV)
        addFAB = findViewById(R.id.idFAB)
          
        // on below line we are setting layout
        // manager to our recycler view.
        notesRV.layoutManager = LinearLayoutManager(this)
          
        // on below line we are initializing our adapter class.
        val noteRVAdapter = NoteRVAdapter(this, this, this)
          
        // on below line we are setting 
        // adapter to our recycler view.
        notesRV.adapter = noteRVAdapter
          
        // on below line we are 
        // initializing our view modal.
        viewModal = ViewModelProvider(
            this,
            ViewModelProvider.AndroidViewModelFactory.getInstance(application)
        ).get(NoteViewModal::class.java)
          
        // on below line we are calling all notes method
        // from our view modal class to observer the changes on list.
        viewModal.allNotes.observe(this, Observer { list ->
            list?.let {
                // on below line we are updating our list.
                noteRVAdapter.updateList(it)
            }
        })
        addFAB.setOnClickListener {
            // adding a click listener for fab button 
            // and opening a new intent to add a new note.
            val intent = Intent(this@MainActivity, AddEditNoteActivity::class.java)
            startActivity(intent)
            this.finish()
        }
    }
  
    override fun onNoteClick(note: Note) {
        // opening a new intent and passing a data to it.
        val intent = Intent(this@MainActivity, AddEditNoteActivity::class.java)
        intent.putExtra("noteType", "Edit")
        intent.putExtra("noteTitle", note.noteTitle)
        intent.putExtra("noteDescription", note.noteDescription)
        intent.putExtra("noteId", note.id)
        startActivity(intent)
        this.finish()
    }
  
    override fun onDeleteIconClick(note: Note) {
        // in on note click method we are calling delete
        // method from our view modal to delete our not.
        viewModal.deleteNote(note)
        // displaying a toast message
        Toast.makeText(this, "${note.noteTitle} Deleted", Toast.LENGTH_LONG).show()
    }
}

Paso 15: trabajar con el archivo AddEditNoteActivity.kt

Vaya a la aplicación > java > el nombre del paquete de su aplicación > AddEditNoteActivity.java y agréguele el siguiente código. Se agregan comentarios en el código para conocer con más detalle. 

Kotlin

package com.gtappdevelopers.noteapplication
  
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import java.text.SimpleDateFormat
import java.util.*
  
class AddEditNoteActivity : AppCompatActivity() {
    // on below line we are creating
    // variables for our UI components.
    lateinit var noteTitleEdt: EditText
    lateinit var noteEdt: EditText
    lateinit var saveBtn: Button
  
    // on below line we are creating variable for 
    // viewmodal and and integer for our note id.
    lateinit var viewModal: NoteViewModal
    var noteID = -1;
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_add_edit_note)
          
        // on below line we are initialing our view modal.
        viewModal = ViewModelProvider(
            this,
            ViewModelProvider.AndroidViewModelFactory.getInstance(application)
        ).get(NoteViewModal::class.java)
          
        // on below line we are initializing all our variables.
        noteTitleEdt = findViewById(R.id.idEdtNoteName)
        noteEdt = findViewById(R.id.idEdtNoteDesc)
        saveBtn = findViewById(R.id.idBtn)
  
        // on below line we are getting data passed via an intent.
        val noteType = intent.getStringExtra("noteType")
        if (noteType.equals("Edit")) {
            // on below line we are setting data to edit text.
            val noteTitle = intent.getStringExtra("noteTitle")
            val noteDescription = intent.getStringExtra("noteDescription")
            noteID = intent.getIntExtra("noteId", -1)
            saveBtn.setText("Update Note")
            noteTitleEdt.setText(noteTitle)
            noteEdt.setText(noteDescription)
        } else {
            saveBtn.setText("Save Note")
        }
  
        // on below line we are adding 
        // click listener to our save button.
        saveBtn.setOnClickListener {
            // on below line we are getting 
            // title and desc from edit text.
            val noteTitle = noteTitleEdt.text.toString()
            val noteDescription = noteEdt.text.toString()
            // on below line we are checking the type 
            // and then saving or updating the data.
            if (noteType.equals("Edit")) {
                if (noteTitle.isNotEmpty() && noteDescription.isNotEmpty()) {
                    val sdf = SimpleDateFormat("dd MMM, yyyy - HH:mm")
                    val currentDateAndTime: String = sdf.format(Date())
                    val updatedNote = Note(noteTitle, noteDescription, currentDateAndTime)
                    updatedNote.id = noteID
                    viewModal.updateNote(updatedNote)
                    Toast.makeText(this, "Note Updated..", Toast.LENGTH_LONG).show()
                }
            } else {
                if (noteTitle.isNotEmpty() && noteDescription.isNotEmpty()) {
                    val sdf = SimpleDateFormat("dd MMM, yyyy - HH:mm")
                    val currentDateAndTime: String = sdf.format(Date())
                    // if the string is not empty we are calling a 
                    // add note method to add data to our room database.
                    viewModal.addNote(Note(noteTitle, noteDescription, currentDateAndTime))
                    Toast.makeText(this, "$noteTitle Added", Toast.LENGTH_LONG).show()
                }
            }
            // opening the new activity on below line
            startActivity(Intent(applicationContext, MainActivity::class.java))
            this.finish()
        }
    }
}

 
Ahora ejecute su aplicación para ver el resultado de la aplicación.

 Producción:

Obtenga el proyecto completo desde aquí .

Publicación traducida automáticamente

Artículo escrito por chaitanyamunje y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *