¿Cómo crear una aplicación de Android de comestibles usando MVVM y la base de datos de habitaciones? – Part 1

En este artículo, vamos a crear una aplicación de comestibles en Android usando Android Studio. Muchas veces nos olvidamos de comprar cosas que queremos comprar, después de todo, no podemos recordar todos los artículos, por lo que con la ayuda de esta aplicación, puede anotar los artículos de abarrotes que va a comprar, haciendo esto no puedes olvidar ningún artículo que quieras comprar. qué

Build a Grocery Android App

En este proyecto, usamos MVVM (Model View ViewModel) para patrones arquitectónicos, Room para base de datos, Coroutines y RecyclerView para mostrar la lista de elementos. Antes de saltar al proyecto, entendamos estos términos.

MVVM (Modelo Vista VistaModelo)

La arquitectura MVVM en Android se utiliza para dar estructura al código del proyecto y comprender el código fácilmente. MVVM es un patrón de diseño arquitectónico en android. MVVM trata las clases de actividad y los archivos XML como vista. Este patrón de diseño separa completamente la interfaz de usuario de su lógica. Aquí hay una imagen para entender rápidamente MVVM.  

MVVM(Model View ViewModel)

Después de ver esta imagen, si no entiende cómo funcionará, no se preocupe, escribiremos el código y lo entenderemos completamente.

Base de datos de habitaciones

La biblioteca de persistencia de habitaciones es una biblioteca de administración de base de datos y se utiliza para almacenar los datos de aplicaciones como el nombre del artículo de comestibles, la cantidad de artículos de comestibles y el precio de los artículos de comestibles. Room es una capa de cobertura en SQLite que ayuda a realizar fácilmente la operación en la base de datos.

RecycleView

RecyclerView es un contenedor y se usa para mostrar la recopilación de datos en una gran cantidad de conjuntos de datos que se pueden desplazar de manera muy efectiva manteniendo un número limitado de vistas.

corrutinas

Las corrutinas son un subproceso liviano, usamos una corrutina para realizar una operación en otros subprocesos, por lo que nuestro subproceso principal no se bloquea y nuestra aplicación no falla. 

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: antes de ir a la sección de codificación, primero debe hacer una tarea previa

Antes de ir a la parte de codificación, primero agregue estas bibliotecas en su archivo gradle y también aplique el complemento como ‘kotlin-kapt’. Para agregar esta biblioteca, vaya a Gradle Scripts > build.gradle(Module:app).

def habitación_versión = “2.2.1”

   def ciclo_de_vida_versión = “2.0.0”

   // Sala y Componentes Arquitectónicos

   implementación “androidx.room:room-runtime:$room_version”

   implementación “androidx.legacy:legacy-support-v4:1.0.0”

   implementación ‘androidx.lifecycle:lifecycle-extensions:2.1.0’

   implementación ‘androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0’

   implementación “androidx.room:room-ktx:2.2.1”

   kapt «androidx.room:room-compiler:$room_version»

   // Corrutinas

   implementación ‘org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0’

   implementación “org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0”

   // Nuevo diseño de materiales

   implementación “com.google.android.material:material:1.0.0”

   // Ver modelo

   implementación «androidx.lifecycle:lifecycle-extensions:$lifecycle_version»

   implementación «androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version»

   kapt «androidx.lifecycle:lifecycle-compiler:$lifecycle_version»

A continuación se muestra el código completo para el archivo build.gradle(:app) .

Kotlin

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
 
android {
    compileSdkVersion 29
    buildToolsVersion "30.0.3"
 
    defaultConfig {
        applicationId "com.example.grocerylist"
        minSdkVersion 16
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
 
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
 
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility = 1.8
        targetCompatibility = 1.8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
}
 
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.core:core-ktx:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
 
    def room_version = "2.2.1"
    def lifecycle_version = "2.0.0"
 
    // Room and Architectural Components
    implementation "androidx.room:room-runtime:$room_version"
    implementation "androidx.legacy:legacy-support-v4:1.0.0"
    implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0'
    implementation "androidx.room:room-ktx:2.2.1"
    kapt "androidx.room:room-compiler:$room_version"
 
    // Coroutines
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0'
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0"
 
    // New Material Design
    implementation "com.google.android.material:material:1.0.0"
 
    // ViewModel
    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
 
}

 
 A continuación se muestra el código del archivo strings.xml . Aquí hemos añadido las strings necesarias que vamos a utilizar en nuestro proyecto. 

XML

<resources>
    <string name="app_name">Fresh Basket</string>
 
    <!-- TODO: Remove or change this placeholder text -->
    <string name="hello_blank_fragment">Hello blank fragment</string>
    <string name="itemName">Banana</string>
    <string name="itemQuantity">35</string>
    <string name="itemPrice">250Rs</string>
    <string name="totalCost">20</string>
    <string name="totalCostTitle">Total Cost</string>
    <string name="title">Add Items to your cart</string>
    <string name="etItem">Item</string>
    <string name="etQuantity">Quantity</string>
    <string name="etPrice">Price</string>
    <string name="save">Save</string>
    <string name="cancel">Cancel</string>
     
</resources>

 
A continuación se muestra el código para el archivo colors.xml . Aquí hemos añadido los colores necesarios que vamos a utilizar en nuestro proyecto. 

XML

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#0AD042</color>
    <color name="colorPrimaryDark">#03551A</color>
    <color name="colorAccent">#03DAC5</color>
    <color name="black">#000000</color>
    <color name="white">#ffffff</color>
</resources>

 
Paso 3: implementar la base de datos de salas

a) Clase de entidades 

La clase de entidades contiene todas las columnas de la base de datos y debe anotarse con @Entity(tablename = “Nombre de la tabla”). La clase de entidad es una clase de datos. Y la anotación de información @Column se usa para ingresar el nombre de la variable de columna y el tipo de datos. También agregaremos la clave principal para el incremento automático. Vaya a aplicación > java > com.example.nombre-aplicación. Haga clic con el botón derecho en com.example.application-name, vaya a nuevo y cree un archivo/clase Kotlin y nombre el archivo como GroceryEntities . Vea el código a continuación para comprenderlo e implementarlo por completo.

Kotlin

package com.example.grocerylist.Database.Entity
 
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
 
// This is a data class which store data.
// Entities class create a table in database,
// in our database we will create three column
 
@Entity(tableName = "grocery_items")
 
data class GroceryItems(
 
    // create itemName variable to
    // store grocery items.
    @ColumnInfo(name = "itemName")
    var itemName: String,
 
    // create itemQuantity variable
    // to store grocery quantity.
    @ColumnInfo(name = "itemQuantity")
    var itemQuantity: Int,
 
    // create itemPrice variable to
    // store grocery price.
    @ColumnInfo(name = "itemPrice")
    var itemPrice: Int
) {
    // Primary key is a unique key
    // for different database.
    @PrimaryKey(autoGenerate = true)
    var id: Int? = null
}

 b) Interfaz Dao 

El Dao es una interfaz en la que creamos todas las funciones que queremos implementar en la base de datos. Esta interfaz también anotó con @Dao. Ahora crearemos una función usando la función de suspensión, que es una función de rutinas. Aquí creamos tres funciones, primero es la función de inserción para insertar elementos en la base de datos y anotados con @Insert, segundo es para eliminar elementos de la base de datos anotados con @Delete y tercero es para obtener todos los elementos anotados con @Query. Vaya a la aplicación > java > com.example.application-name . Haga clic con el botón derecho en com.example.application-name, vaya a nuevo y cree el archivo/clase de Kotlin y nombre el archivo como GroceryDao . Vea el código a continuación para implementar.

Kotlin

package com.example.grocerylist.Database
 
import androidx.lifecycle.LiveData
import androidx.room.*
import com.example.grocerylist.Database.Entity.GroceryItems
 
// This class is used to create
// function for database.
@Dao
interface GroceryDao {
 
    // Insert function is used to
    // insert data in database.
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(item: GroceryItems)
 
    // Delete function is used to
    // delete data in database.
    @Delete
    suspend fun delete(item: GroceryItems)
 
    // getAllGroceryItems function is used to get
    // all the data of database.
    @Query("SELECT * FROM grocery_items")
    fun getAllGroceryItems(): LiveData<List<GroceryItems>>
}

c) Clase de base de datos

Clase de base de datos anotada con @Database(entities = [Name of Entity class.class], version = 1) estas entidades son la array de entidades que enumera todas las entidades de datos asociadas con la base de datos y la versión muestra la versión actual de la base de datos. Esta clase de base de datos hereda de la clase Room Database. En la clase GroceryDatabase crearemos un método abstracto para obtener una instancia de DAO y usaremos este método desde la instancia de DAO para interactuar con la base de datos. Vea el siguiente código para implementar. Vaya a la aplicación > java > com.example.application-name . Haga clic con el botón derecho en com.example.application-name, vaya a new y cree el archivo/clase de Kotlin como GroceryDatabase . Vea el código a continuación para implementar.

Kotlin

package com.example.grocerylist.Database
 
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.example.grocerylist.Database.Entity.GroceryItems
 
@Database(entities = [GroceryItems::class], version = 1)
abstract class GroceryDatabase : RoomDatabase() {
 
    abstract fun getGroceryDao(): GroceryDao
 
    companion object {
        @Volatile
        private var instance: GroceryDatabase? = null
        private val LOCK = Any()
 
        operator fun invoke(context: Context) = instance ?: synchronized(LOCK) {
            instance ?: createDatabase(context).also {
                instance = it
            }
        }
 
        private fun createDatabase(context: Context) =
            Room.databaseBuilder(context.applicationContext, GroceryDatabase::class.java, "GroceryDatabase.db").build()
    }
}

Paso 4: Ahora implementaremos la estructura arquitectónica en la aplicación 

a) Clase de repositorio

El repositorio es una de las estructuras de diseño. La clase de repositorio proporciona los datos a la clase ViewModel y luego la clase ViewModel usa esos datos para las Vistas. El repositorio elegirá los datos apropiados localmente o en la red. Aquí, en nuestro depósito de comestibles, los datos de clase se obtienen localmente de la base de datos de habitaciones. Agregaremos valor de constructor al crear una instancia de la base de datos y almacenarla en la variable db en la clase Grocery Repository. Vaya a la aplicación > java > com.example.application-name . Haga clic con el botón derecho en com.example.application-name, vaya a new y cree el archivo/clase de Kotlin como GroceryRepository . Vea el código a continuación para implementar.

Kotlin

package com.example.grocerylist.Database
 
import com.example.grocerylist.Database.Entity.GroceryItems
 
class GroceryRepository(private val db: GroceryDatabase) {
 
    suspend fun insert(item: GroceryItems) = db.getGroceryDao().insert(item)
    suspend fun delete(item: GroceryItems) = db.getGroceryDao().delete(item)
 
    fun allGroceryItems() = db.getGroceryDao().getAllGroceryItems()
}

Ve a app > java > com.example.application-name . Haga clic derecho en com.example.application-name, vaya a nuevo y cree un nuevo paquete llamado UI y luego haga clic derecho en el paquete UI y cree un archivo/clase de Kotlin. Vea el código a continuación para implementar.

b) clase de modelo de vista 

Clase ViewModel utilizada como interfaz entre View y Data. La clase Grocery View Model se hereda de la clase View Model y pasaremos el valor del constructor al crear una variable de instancia de la clase Repository y almacenarla en la variable del repositorio. A medida que pasamos el constructor en View Model, tenemos que crear otra clase que sea una clase Factory View Model. Vaya a app > java > com.example.application-name > UI . Haga clic con el botón derecho en el paquete de UI y cree un archivo/clase de Kotlin y nombre el archivo como GroceryViewModel . Vea el siguiente código.

Kotlin

package com.example.grocerylist.UI
 
import androidx.lifecycle.ViewModel
import com.example.grocerylist.Database.Entity.GroceryItems
import com.example.grocerylist.Database.GroceryRepository
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
 
class GroceryViewModel(private val repository: GroceryRepository) : ViewModel() {
 
    // In coroutines thread insert item in insert function.
    fun insert(item: GroceryItems) = GlobalScope.launch {
        repository.insert(item)
    }
 
    // In coroutines thread delete item in delete function.
    fun delete(item: GroceryItems) = GlobalScope.launch {
        repository.delete(item)
    }
 
    //Here we initialized allGroceryItems function with repository
    fun allGroceryItems() = repository.allGroceryItems()
 
}

 c) clase de modelo de vista de fábrica  

Heredaremos la clase Grocery ViewModel Factory de ViewModelProvider.NewInstanceFactory y nuevamente pasaremos el valor del constructor creando una variable de instancia de Grocery Repository y devolveremos GroceryViewModel (repositorio). Vaya a la aplicación > java > com.example.application-name > UI . Haga clic con el botón derecho en el paquete de la interfaz de usuario y cree un nombre de clase/archivo Kotlin GroceryViewModelFactory . Vea el siguiente código para entender.

Kotlin

package com.example.grocerylist.UI
 
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.example.grocerylist.Database.GroceryRepository
 
class GroceryViewModelFactory(private val repository: GroceryRepository):ViewModelProvider.NewInstanceFactory() {
 
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return GroceryViewModel(repository) as T
    }
}

 
 Paso 5: ahora pasemos a la parte de la interfaz de usuario 

En el archivo activity_main.xml , agregaremos dos ImageView , RecyclerView y Button después de hacer clic en este botón, se abre un cuadro de diálogo y en ese cuadro de diálogo el usuario puede ingresar el nombre del artículo, la cantidad del artículo y el precio del artículo. Consulte el siguiente código.

XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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="#ffffff"
    android:orientation="vertical"
    tools:context=".UI.MainActivity">
 
    <!-- To create a app bar with logo image. -->
    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:src="@drawable/logo"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />
 
    <!-- In this image view we will add a title image -->
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="35dp"
        android:src="@drawable/title"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.497"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView2"
        app:layout_constraintVertical_bias="0.0" />
 
    <!-- Recycler View to display list -->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvList"
        android:layout_width="match_parent"
        android:layout_height="470dp"
        android:background="@color/white"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView"
        app:layout_constraintVertical_bias="1.0">
         
    </androidx.recyclerview.widget.RecyclerView>
 
    <!-- This button is used to open dialog box in
         which user can enter grocery items -->
    <Button
        android:id="@+id/btnAdd"
        android:layout_width="60dp"
        android:layout_height="wrap_content"
        android:background="@drawable/button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.954"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView"
        app:layout_constraintVertical_bias="0.969" />
     
</androidx.constraintlayout.widget.ConstraintLayout>

 Salida de código XML:

Paso 6: implementemos RecyclerView . Ahora codificaremos la parte de la interfaz de usuario de la fila en la lista. Vaya a aplicación > res > diseño . Haga clic con el botón derecho en el diseño, vaya a nuevo y luego agregue un archivo de recursos de diseño y asígnele el nombre de adaptador de comestibles . Consulte el código XML del archivo Grooveadapter.xml .

XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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="125dp"
    android:background="@drawable/adapter1">
 
    <!-- To display item name in recycler view -->
    <TextView
        android:id="@+id/txtItemName"
        android:layout_width="0dp"
        android:layout_height="53dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="15dp"
        android:layout_marginRight="15dp"
        android:layout_marginBottom="17dp"
        android:fontFamily="@font/rokkitt"
        android:text="@string/itemName"
        android:textColor="@color/white"
        android:textSize="35sp"
        app:layout_constraintBottom_toTopOf="@+id/txtTotalCostTitle"
        app:layout_constraintEnd_toStartOf="@+id/txtItemQuantity"
        app:layout_constraintStart_toEndOf="@+id/cbItemCheck"
        app:layout_constraintTop_toTopOf="parent" />
 
    <!-- To display item quantity -->
    <TextView
        android:id="@+id/txtItemQuantity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="34dp"
        android:layout_marginRight="34dp"
        android:layout_marginBottom="9dp"
        android:text="@string/itemQuantity"
        android:textColor="@color/white"
        android:textSize="25sp"
        app:layout_constraintBottom_toBottomOf="@+id/txtItemName"
        app:layout_constraintEnd_toStartOf="@+id/txtItemPrice"
        app:layout_constraintStart_toEndOf="@+id/txtItemName"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="1.0" />
 
    <!-- To display item price -->
    <TextView
        android:id="@+id/txtItemPrice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="26dp"
        android:layout_marginEnd="22dp"
        android:layout_marginRight="22dp"
        android:layout_marginBottom="26dp"
        android:text="@string/itemPrice"
        android:textColor="@color/white"
        android:textSize="25sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/txtItemTotalCost"
        app:layout_constraintEnd_toStartOf="@+id/ibDelete"
        app:layout_constraintStart_toEndOf="@+id/txtItemQuantity"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />
 
    <CheckBox
        android:id="@+id/cbItemCheck"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="29dp"
        android:layout_marginLeft="29dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:background="@color/white"
        android:shadowColor="@color/black"
        app:layout_constraintBaseline_toBaselineOf="@+id/txtItemName"
        app:layout_constraintEnd_toStartOf="@+id/txtItemName"
        app:layout_constraintStart_toStartOf="parent" />
 
    <!-- This button is used to delete grocery item  -->
    <ImageButton
        android:id="@+id/ibDelete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="26dp"
        android:layout_marginRight="26dp"
        android:background="@color/black"
        android:src="@drawable/ic_action_delete"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/txtItemPrice"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.257" />
 
    <!-- To display total cost of grocery items -->
    <TextView
        android:id="@+id/txtItemTotalCost"
        android:layout_width="100dp"
        android:layout_height="60dp"
        android:background="@drawable/adapter2"
        android:padding="8dp"
        android:paddingLeft="12dp"
        android:text="@string/totalCost"
        android:textSize="30sp"
        android:textStyle="bold"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/txtTotalCostTitle"
        app:layout_constraintTop_toTopOf="@+id/txtTotalCostTitle"
        app:layout_constraintVertical_bias="0.875" />
 
    <!-- This text view is used to add statement for total cost  -->
    <TextView
        android:id="@+id/txtTotalCostTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="77dp"
        android:layout_marginLeft="77dp"
        android:layout_marginEnd="149dp"
        android:layout_marginRight="149dp"
        android:layout_marginBottom="16dp"
        android:text="@string/totalCostTitle"
        android:textColor="@color/white"
        android:textSize="20dp"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/txtItemTotalCost"
        app:layout_constraintStart_toStartOf="parent" />
     
</androidx.constraintlayout.widget.ConstraintLayout>

 Salida de código XML:

 Codificaremos la clase de adaptador para la vista del reciclador. En la clase Grocery Adapter, agregaremos el valor del constructor al almacenar la clase de entidades como una lista en la variable de lista y crearemos una instancia del modelo de vista. En Grocery Adapter anularemos tres funciones: onCreateViewHolder, getItemCount y onbindViewHolder, también crearemos una clase interna llamada titular de vista de supermercado. Vaya a la aplicación > java > com.example.application-name . Haga clic con el botón derecho en com.example.application-name, vaya a nuevo y cree un nuevo paquete llamado Adapter y luego haga clic con el botón derecho en el paquete Adapter y cree un nombre de clase/archivo Kotlin GroceryAdapter . Vea el siguiente código.

Kotlin

package com.example.grocerylist.Adapter
 
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.grocerylist.Database.Entity.GroceryItems
import com.example.grocerylist.R
import com.example.grocerylist.UI.GroceryViewModel
import kotlinx.android.synthetic.main.groceryadapter.view.*
 
class GroceryAdapter(var list: List<GroceryItems>, val viewModel: GroceryViewModel) :
    RecyclerView.Adapter<GroceryAdapter.GroceryViewHolder>() {
 
    // In this function we will add our groceryadapter.xml to kotlin class
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GroceryViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.groceryadapter, parent, false)
        return GroceryViewHolder(view)
    }
 
    // This function is used to return total number of size of list.
    override fun getItemCount(): Int {
        return list.size
    }
 
    // In onBindViewHolder we will bind our itemViews with adapter
    override fun onBindViewHolder(holder: GroceryViewHolder, position: Int) {
        var currentPosition = list[position]
        holder.itemView.txtItemName.text = currentPosition.itemName
        holder.itemView.txtItemPrice.text = "${currentPosition.itemPrice}"
        holder.itemView.txtItemQuantity.text = "${currentPosition.itemQuantity}"
        holder.itemView.ibDelete.setOnClickListener {
            viewModel.delete(currentPosition)
        }
 
        // To get total cost
        if (position == list.size - 1) {
            var totalCost = 0
            for (i in 0 until list.size) {
                totalCost += list[i].itemPrice
            }
            holder.itemView.txtItemTotalCost.visibility = View.VISIBLE
            holder.itemView.txtTotalCostTitle.visibility = View.VISIBLE
            holder.itemView.txtItemTotalCost.text = "$totalCost"
        }
    }
    // Inner class for viewHolder
    inner class GroceryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
}

 Paso 7: Para ingresar el artículo de comestibles, la cantidad y el precio del usuario, debemos crear una interfaz. Para implementar esta interfaz usaremos DialogBox. Primero cree la interfaz de usuario del cuadro de diálogo. En este cuadro de diálogo agregaremos tres editar texto y dos vistas de texto. Tres texto de edición para ingresar el nombre, la cantidad y el precio del artículo de comestibles. Dos vistas de texto, una para guardar y otra para cancelar. Después de hacer clic en Guardar texto, todos los datos se guardan en la base de datos y al hacer clic en el cuadro de diálogo Cancelar texto se cierra. Vaya a la aplicación > res > diseño . Haga clic con el botón derecho en el diseño , vaya a nuevo y luego agregue un archivo de recursos de diseño y asígnele el nombre de diálogo de comestibles . Consulte el código xml del archivo Groovedialog.xml .

XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="310dp"
    android:layout_height="250dp"
    android:background="@drawable/rectangle">
 
    <!-- To display title-->
    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:layout_marginEnd="5dp"
        android:layout_marginRight="5dp"
        android:layout_marginBottom="26dp"
        android:text="@string/title"
        android:textColor="@color/black"
        android:textSize="30dp"
        app:layout_constraintBottom_toTopOf="@+id/linearLayout"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 
    <!-- Linear Layout is used to give equal
         weight sum to edit text-->
    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="66dp"
        android:weightSum="3"
        app:layout_constraintBottom_toTopOf="@+id/tvSave"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tvTitle">
 
        <!-- Edit Text is used to Enter Grocery
             Item Name by user-->
        <EditText
            android:id="@+id/etItemName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="0dp"
            android:layout_weight="1"
            android:hint="@string/etItem"
            android:textSize="30dp"
            app:layout_constraintBottom_toTopOf="@+id/tvCancel"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.069"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.661" />
 
        <!-- Edit Text is used to Enter Grocery
             Item Quantity by user-->
        <EditText
            android:id="@+id/etItemQuantity"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="0dp"
            android:layout_weight="1"
            android:hint="@string/etQuantity"
            android:inputType="number"
            android:textSize="30dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/etItemPrice"
            app:layout_constraintHorizontal_bias="0.461"
            app:layout_constraintStart_toEndOf="@+id/etItemName"
            app:layout_constraintTop_toBottomOf="@+id/tvTitle"
            app:layout_constraintVertical_bias="0.276" />
 
        <!-- Edit Text is used to Enter Grocery
             Item Price by user-->
        <EditText
            android:id="@+id/etItemPrice"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="0dp"
            android:layout_weight="1"
            android:hint="@string/etPrice"
            android:inputType="number"
            android:textSize="30dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.861"
            app:layout_constraintStart_toEndOf="@+id/etItemName"
            app:layout_constraintTop_toTopOf="parent" />
 
    </LinearLayout>
 
    <!-- Text view is used as save button to save
         all details in database by user-->
    <TextView
        android:id="@+id/tvSave"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:layout_marginBottom="14dp"
        android:text="@string/save"
        android:textColor="@color/black"
        android:textSize="20dp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/tvCancel"
        app:layout_constraintTop_toBottomOf="@+id/linearLayout" />
 
    <!-- Text View is used to close dialog box-->
    <TextView
        android:id="@+id/tvCancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="28dp"
        android:layout_marginLeft="28dp"
        android:layout_marginEnd="154dp"
        android:layout_marginRight="154dp"
        android:layout_marginBottom="14dp"
        android:text="@string/cancel"
        android:textColor="@color/black"
        android:textSize="20dp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/tvSave"
        app:layout_constraintStart_toStartOf="parent" />
 
</androidx.constraintlayout.widget.ConstraintLayout>

 Salida de código XML:

Para agregar un oyente de clics al guardar texto, primero debemos crear una interfaz en la que creamos una función. Vaya a la aplicación > java > com.example.application-name > UI. Haga clic con el botón derecho en el paquete de interfaz de usuario y cree un archivo/clase de Kotlin y cree un nombre de interfaz como DialogListener . Consulte el código del archivo DialogListener.kt .

Kotlin

package com.example.grocerylist.UI
 
import com.example.grocerylist.Database.Entity.GroceryItems
 
interface DialogListener {
   
    // Create a function to add items
      // in GroceryItems on clicking
    fun onAddButtonClicked(item:GroceryItems)
}

Ahora crearemos una clase de diálogo de comestibles en la que guardaremos todas las entradas en diferentes variables y luego las insertaremos en la base de datos. Vaya a la aplicación > Java > com.example.application-name > UI. Haga clic con el botón derecho en el paquete de la interfaz de usuario y cree un archivo/clase de Kotlin y cree un nombre de clase GroceryItemDialog . Vea el siguiente código.

Kotlin

package com.example.grocerylist.UI
 
import android.content.Context
import android.os.Bundle
import android.view.Window
import android.widget.Toast
import androidx.appcompat.app.AppCompatDialog
import com.example.grocerylist.Database.Entity.GroceryItems
import com.example.grocerylist.R
import kotlinx.android.synthetic.main.grocerydialog.*
 
class GroceryItemDialog(context: Context, var dialogListener: DialogListener) : AppCompatDialog(context) {
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
        setContentView(R.layout.grocerydialog)
 
        // Click listener on Save button
        // to save all data.
        tvSave.setOnClickListener {
 
            // Take all three inputs in different variables from user
            // and add it in Grocery Items database
            val name = etItemName.text.toString()
            val quantity = etItemQuantity.text.toString().toInt()
            val price = etItemPrice.text.toString().toInt()
 
            // Toast to display enter items in edit text
            if (name.isEmpty()) {
                Toast.makeText(context, "Please Enter Item Name", Toast.LENGTH_SHORT).show()
            }
 
            val item = GroceryItems(name, quantity, price)
            dialogListener.onAddButtonClicked(item)
            dismiss()
        }
 
        // On click listener on cancel text to close dialog box
        tvCancel.setOnClickListener {
            cancel()
        }
    }
}

Paso 8: En este paso finalmente codificaremos en nuestra MainActivity. En nuestra actividad principal, tenemos que configurar la vista del reciclador y agregar, haga clic en el oyente en el botón Agregar para abrir el cuadro de diálogo. Vaya al archivo MainActivity.kt y consulte el siguiente código. A continuación se muestra el código del archivo MainActivity.kt . Se agregan comentarios dentro del código para comprender el código con más detalle.

Kotlin

package com.example.grocerylist.UI
 
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.grocerylist.Adapter.GroceryAdapter
import com.example.grocerylist.Database.Entity.GroceryItems
import com.example.grocerylist.Database.GroceryDatabase
import com.example.grocerylist.Database.GroceryRepository
import com.example.grocerylist.R
import kotlinx.android.synthetic.main.activity_main.*
 
class MainActivity : AppCompatActivity() {
     
    lateinit var ViewModel: GroceryViewModel
    lateinit var list: List<GroceryItems>
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
         
        val groceryRepository = GroceryRepository(GroceryDatabase(this))
        val factory = GroceryViewModelFactory(groceryRepository)
 
        // Initialised View Model
        ViewModel = ViewModelProvider(this, factory).get(GroceryViewModel::class.java)
        val groceryAdapter = GroceryAdapter(listOf(), ViewModel)
        rvList.layoutManager = LinearLayoutManager(this)
        rvList.adapter = groceryAdapter
         
        // To display all items in recycler view
        ViewModel.allGroceryItems().observe(this, Observer {
            groceryAdapter.list = it
            groceryAdapter.notifyDataSetChanged()
        })
         
        // on ClickListener on button to open dialog box
        btnAdd.setOnClickListener {
            GroceryItemDialog(this, object : DialogListener {
                override fun onAddButtonClicked(item: GroceryItems) {
                    ViewModel.insert(item)
                }
            }).show()
        }
    }
}

 
 Así es como se ve la estructura completa del proyecto.
 

Producción:

Enlace Github: https://github.com/arpit-288/Fresh_Basket

Publicación traducida automáticamente

Artículo escrito por arpitsrivastava288 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 *