You are on page 1of 10

Pasos para hacer un registro en Android Studio

1- Configuramos buil-gradle(project)

buildscript {
ext {
compose_version = '1.3.3'
room_version = '2.5.0'
}
}// Top-level build file where you can add configuration options common
to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.4.0-rc03' apply false
id 'com.android.library' version '7.4.0-rc03' apply false
id 'org.jetbrains.kotlin.android' version '1.7.20' apply false
id 'com.google.dagger.hilt.android' version '2.44' apply false
}
2- Configuramos buil-gradle(module)

 Agregamos puglins
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'

id 'kotlin-kapt'
id 'com.google.dagger.hilt.android'
}

 Ponemos versión de compilación


composeOptions {
kotlinCompilerExtensionVersion '1.3.2'
}
 Agregamos dependencias
dependencies {
//Import the Compose BOM
def composeBom = platform('androidx.compose:compose-bom:2023.01.00')
implementation composeBom
androidTestImplementation composeBom

// compose.ui
implementation "androidx.compose.ui:ui"
implementation 'androidx.compose.ui:ui-tooling-preview'
debugImplementation 'androidx.compose.ui:ui-tooling'

//material
implementation 'androidx.compose.material3:material3'
implementation 'androidx.compose.material:material-icons-core'
implementation 'androidx.compose.material:material-icons-extended'

implementation 'androidx.core:core-ktx:1.9.0'
implementation "androidx.activity:activity-compose:1.6.1"
//navegacion
implementation "androidx.navigation:navigation-compose:2.5.3"

//Lifecycle-runtime
def lifecycle_version = "2.5.1"
implementation "androidx.lifecycle:lifecycle-runtime-
ktx:$lifecycle_version"

// Integration with ViewModels


implementation "androidx.lifecycle:lifecycle-viewmodel-
compose:$lifecycle_version"

//Coroutines
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"

//Room
implementation("androidx.room:room-runtime:$room_version")
implementation("androidx.room:room-ktx:$room_version")
annotationProcessor("androidx.room:room-compiler:$room_version")
kapt "androidx.room:room-compiler:$room_version"

//Hilt
implementation "com.google.dagger:hilt-android:2.44"
kapt "com.google.dagger:hilt-compiler:2.44"
implementation "androidx.hilt:hilt-navigation-compose:1.0.0"

// testing dependencies
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
debugImplementation 'androidx.compose.ui:ui-test-manifest'

testImplementation "junit:junit:4.13.2"
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
testImplementation "com.google.truth:truth:1.1.3"
androidTestImplementation "com.google.truth:truth:1.1.3"
androidTestImplementation "androidx.test.espresso:espresso-core:3.5.1"
androidTestImplementation "android.arch.core:core-testing:1.1.1"

testImplementation "androidx.room:room-testing:$room_version"
androidTestImplementation "app.cash.turbine:turbine:0.9.0"
}

3- Sincronizamos y luego compilamos

Si todo está bien seguimos con el paso 4

4- Creamos una clase con el nombre de la aplicación


5- Entramos al manifests y escribimos 3 letras nam y le damos enter. Automáticamente se
agregara la clase que hicimos anteriormente

6- Agregamos el AndroidEntryPoint en el MainActivity

7- Creamos las carpetas que vamos a utilizar. Se crean dándole click derecho > open in >
terminal.

Y en la terminal hacemos la carpeta data y di con el comando md “nombre”. Si queremos


entrar a una carpeta y hacer más carpeta dentro de ellas le damos cd “nombre de la
carpeta”. Dentro de la carpeta data va otras carpetas llamada local, remote y repository.
Dentro de local tenemos la carpeta dao, entity y un archivo que será nuestra base de
datos.
Asi quedarías las carpetas en orden:

8- Creamos una clase dentro de la carpeta entity y creamos las entidades

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "Ocupaciones")
data class OcupacionEntity(
@PrimaryKey(autoGenerate = true)
val ocupacionId: Int?=null,
val descripcion:String,
val sueldo:Double) {
}

9- Creamos una interface en la carpeta dao y declaramos los métodos que utilizaremos

import androidx.room.*
import com.edu.ucne.te_presto_app.data.local.entity.OcupacionEntity
import kotlinx.coroutines.flow.Flow
@Dao
interface OcupacionDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(ocupacionEntity: OcupacionEntity)

@Delete
suspend fun delete(ocupacionEntity: OcupacionEntity)

@Query("""
SELECT *
FROM Ocupaciones
WHERE OcupacionId=:ocupacionId
LIMIT 1
""")
suspend fun find(ocupacionId: Int): OcupacionEntity?

@Query("""SELECT *
FROM Ocupaciones
ORDER BY ocupacionId desc
""")
fun getList(): Flow<List<OcupacionEntity>>

class dao{
fun save():Boolean{
return true
}
}
10- En la carpeta local creamos una clase que será nuestra base de datos

import androidx.room.Database
import androidx.room.RoomDatabase
import com.edu.ucne.te_presto_app.data.local.dao.OcupacionDao
import com.edu.ucne.te_presto_app.data.local.entity.OcupacionEntity

@Database(
entities = [
OcupacionEntity::class
],
version = 1
)

abstract class TePrestoDb: RoomDatabase(){


abstract val ocupacionDao: OcupacionDao
}

11- En la carpeta di creamos un objeto que será AppModulo


import android.content.Context
import androidx.room.Room
import com.edu.ucne.te_presto_app.data.local.TePrestoDb
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object AppModule {

@Singleton
@Provides
fun providesDataBase(@ApplicationContext context: Context):
TePrestoDb{
return Room.databaseBuilder(
context,
TePrestoDb::class.java,
name = "Tepresto.db"
).fallbackToDestructiveMigration().build()
}
@Singleton
@Provides
fun providesOcupacionDao(db: TePrestoDb) = db.ocupacionDao
}

12- En la carpeta repository creamos una clase para nuestro repository


import com.edu.ucne.te_presto_app.data.local.dao.OcupacionDao
import com.edu.ucne.te_presto_app.data.local.entity.OcupacionEntity
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class OcupacionRepository @Inject constructor(


private val ocupacionDao: OcupacionDao
) {
suspend fun insert(ocupacion: OcupacionEntity){
return ocupacionDao.insert(ocupacion)
}
suspend fun delete(ocupacion: OcupacionEntity) =
ocupacionDao.delete(ocupacion)

suspend fun fin(ocupacionId: Int) = ocupacionDao.find(ocupacionId )


fun getList():Flow<List<OcupacionEntity>> = ocupacionDao.getList()
}
13- Creamos el test del Dao y para eso creamos una clase en la carpeta dao, hacemos un
método save() le damos click derecho > generate > test. Seleccionamos los métodos y le
damos a ok. Luego podemos utilizar el siguiente codigo

internal class Ocupacion_DaoTest {

private lateinit var database: TePrestoDb


private lateinit var dao : OcupacionDao

@Before
fun setUp() {
database= Room.inMemoryDatabaseBuilder(
ApplicationProvider.getApplicationContext(),
TePrestoDb::class.java
).allowMainThreadQueries().build()

dao= database.ocupacionDao
}

@Test
fun Insert_Ocupacion_Is_Success() = runBlocking {
//arrange
val id=1
val ocupacionInsertar = OcupacionEntity(
ocupacionId = id,
descripcion = "Ingeniero Sistemas",
sueldo = 0.0
)

//act
dao.insert(ocupacionInsertar)
var ocupacionBuscada = dao.find(id)

//ocupacionBuscada= ocupacionBuscada?.copy(sueldo = 10.0)


//assert
Truth.assertThat(ocupacionBuscada).isEqualTo(ocupacionInsertar)

@After
fun tearDown() {
database.close()
}
14- En la carpeta ui creamos otra carpeta y dentro de ella creamos el Screen y ViewModel

15- En el Screen tendremos lo que vera el usuario, ósea dibujamos los text, botones, etc.
Hacemos el cuerpo, la consulta, etc. Por ejemplo…
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Save
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.edu.ucne.te_presto_app.data.local.entity.OcupacionEntity

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun OcupacionScreen(viewModel: OcupacionViewModel = hiltViewModel()) {

Column(Modifier.fillMaxSize()) {
OcupacionBody(viewModel)

val uiState by viewModel.uiState.collectAsState()


OcupacionListScreen(uiState.ocupacionesList)
}
}

@Composable
@OptIn(ExperimentalMaterial3Api::class)
private fun OcupacionBody(
viewModel: OcupacionViewModel
) {
Column(modifier = Modifier.fillMaxWidth()) {

OutlinedTextField(
modifier = Modifier
.padding(8.dp)
.fillMaxWidth(),
value = viewModel.descripcion,
onValueChange = { viewModel.descripcion = it },
label = { Text("Descripción") }
)

OutlinedTextField(
modifier = Modifier
.padding(8.dp)
.fillMaxWidth(),
value = viewModel.sueldo,
onValueChange = { viewModel.sueldo = it },
label = { Text("Salario") }
)

ExtendedFloatingActionButton(
modifier = Modifier
.padding(8.dp)
.fillMaxWidth(),
text = { Text("Guardar") },
icon = { Icon(imageVector = Icons.Filled.Save, contentDescription
= "Save") },
onClick = { viewModel.insertar() }
)
}
}

@Composable
private fun OcupacionListScreen(ocupacionList: List<OcupacionEntity>) {
LazyColumn {
items(ocupacionList) { ocupacion ->
OcupacionRow(ocupacion)
}
}
}
@Composable
private fun OcupacionRow(ocupacion: OcupacionEntity) {
Column(
Modifier
.fillMaxWidth()
.padding(8.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
) {
Text(
text = ocupacion.descripcion,
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.weight(3f)
)
Text(
String.format("%.2f", ocupacion.sueldo),
textAlign = TextAlign.End,
modifier = Modifier.weight(2f)
)
}
Divider(Modifier.fillMaxWidth())
}
}

16- Y en el ViewModel tenemos la uiState, métodos como insertar, llamamos le repository,


etc. Por ejemplo…

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
import androidx.compose.runtime.*
import com.edu.ucne.te_presto_app.data.local.entity.OcupacionEntity
import com.edu.ucne.te_presto_app.data.repository.OcupacionRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.update

data class OcupacionUiState(


val ocupacionesList: List<OcupacionEntity> = emptyList()
)

@HiltViewModel
class OcupacionViewModel @Inject constructor(
private val ocupacionRepository: OcupacionRepository
) : ViewModel() {

var descripcion by mutableStateOf("")


var sueldo by mutableStateOf("")

var uiState = MutableStateFlow(OcupacionUiState())


private set

init {
getLista()
}

fun getLista() {
viewModelScope.launch(Dispatchers.IO) {
ocupacionRepository.getList().collect{lista ->
uiState.update {
it.copy(ocupacionesList = lista)
}
}
}
}

fun insertar() {
val ocupacion = OcupacionEntity(
descripcion = descripcion,
sueldo = sueldo.toDoubleOrNull() ?: 0.0
)

viewModelScope.launch(Dispatchers.IO) {
ocupacionRepository.insert(ocupacion)
Limpiar()
}
}

private fun Limpiar() {


descripcion = ""
sueldo = ""
}

You might also like