Professional Documents
Culture Documents
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'
}
// 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"
//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"
}
7- Creamos las carpetas que vamos a utilizar. Se crean dándole click derecho > open in >
terminal.
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
)
@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
}
@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)
@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)
@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())
}
}
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
@HiltViewModel
class OcupacionViewModel @Inject constructor(
private val ocupacionRepository: OcupacionRepository
) : ViewModel() {
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()
}
}