En esta entrada te propongo un ejercicio práctico y guiado para Android en Kotlin, donde construirás una app sencilla de un cronómetro progresivo usando Coroutines. Es una versión simplificada del clásico ejercicio con múltiples cronos.
Ideal si estás aprendiendo Android y quieres practicar:
- Interfaces con
EditText
,TextView
yButton
- Uso de
Coroutines
para tareas asíncronas - Lógica básica de control y validación
🎯 ¿Qué vamos a hacer?
Una app que permita al usuario:
- Ingresar un número máximo de segundos
- Iniciar el conteo desde cero hasta ese número
- Detenerlo o reiniciarlo en cualquier momento
Todo esto se mostrará en una interfaz limpia, sin complicaciones.
🧰 Requisitos
- Android Studio actualizado
- Kotlin como lenguaje
- SDK mínimo: 21 (Android 5.0 Lollipop)
- Coroutines habilitadas
1. 🛠 Crear el proyecto
- Abre Android Studio
- Selecciona New Project > Empty Activity
- Nombra el proyecto
MiniCronometro
- Elige Kotlin como lenguaje y
minSdk 21
2. ⚙️ Configurar dependencias
Abre tu archivo build.gradle (Module: app)
y agrega estas líneas si no están:
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1")
}
Luego sincroniza tu proyecto.
3. 🧩 Crear la interfaz (activity_main.xml)
Copia esto dentro de tu archivo res/layout/activity_main.xml
:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="24dp"
android:orientation="vertical"
android:gravity="center_horizontal">
<EditText
android:id="@+id/editMax"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Máximo en segundos"
android:inputType="number" />
<TextView
android:id="@+id/txtCounter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textSize="64sp"
android:layout_marginTop="24dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:layout_marginTop="24dp">
<Button
android:id="@+id/btnStart"
android:text="Iniciar" />
<Button
android:id="@+id/btnStop"
android:text="Detener"
android:layout_marginStart="8dp" />
<Button
android:id="@+id/btnReset"
android:text="Reiniciar"
android:layout_marginStart="8dp" />
</LinearLayout>
</LinearLayout>
4. 🧠 Lógica en Kotlin (MainActivity.kt)
Reemplaza el contenido de MainActivity.kt
con este:
class MainActivity : AppCompatActivity() {
private lateinit var txtCounter: TextView
private var job: Job? = null
private var current = 0
private var max = 0
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val editMax = findViewById<EditText>(R.id.editMax)
txtCounter = findViewById(R.id.txtCounter)
val btnStart = findViewById<Button>(R.id.btnStart)
val btnStop = findViewById<Button>(R.id.btnStop)
val btnReset = findViewById<Button>(R.id.btnReset)
btnStart.setOnClickListener {
max = editMax.text.toString().toIntOrNull() ?: 0
if (max in 1..9999) {
startCounter()
} else {
editMax.error = "Introduce un número válido (1 a 9999)"
}
}
btnStop.setOnClickListener {
job?.cancel()
}
btnReset.setOnClickListener {
job?.cancel()
current = 0
txtCounter.text = "0"
}
}
private fun startCounter() {
job?.cancel()
job = scope.launch {
while (current < max) {
delay(1000)
current++
txtCounter.text = current.toString()
}
}
}
override fun onDestroy() {
super.onDestroy()
scope.cancel()
}
}
🧪 Prueba final
- Escribe un número (por ejemplo, 10)
- Pulsa Iniciar
- Verás cómo aumenta el contador cada segundo
- Puedes detener o reiniciar en cualquier momento
🧱 Ideas para ampliarlo
- Agregar un
ProgressBar
- Notificación cuando llegue al máximo
- Vibrar o reproducir sonido al finalizar
- Guardar estado usando
ViewModel
✅ Conclusión
Este mini-ejercicio te permite entender cómo usar coroutines para manejar tareas temporizadas sin bloquear la interfaz de usuario. Si ya te manejas con este, ¡puedes animarte a hacer un multicronómetro con RecyclerView como el del ejemplo más avanzado!
¿Te gustaría que subiera este código completo a GitHub? ¿Quieres un vídeo paso a paso?
Déjamelo en los comentarios 👇
