Esta página fue traducida automáticamente del portugués y puede contener errores. La versión en portugués es la canónica.
Cómo acceder a la base de datos fuera de la paint thread
Propósito. Las consultas pesadas (escaneos, bulk, migraciones) bloquean la UI si se ejecutan en la paint thread única de CrossFly. La regla es: haz el I/O de la base de datos en un hilo de trabajo y actualiza la UI solo vía Component.onUI(...), que reenvía el código al hilo de UI.
APIs usadas
new Thread(Runnable).start()— crea un hilo de trabajo para el acceso a la base de datos. Todo elSqliteDb/query/bulkInsertse ejecuta aquí, lejos de la paint thread.Component.onUI(Runnable r)— encolarpara ejecutarse en el hilo de UI (internamenteGdx.app.postRunnable). Toda manipulación de componentes (asignar texto, agregar ítems a la lista,repaint) debe ocurrir dentro de este callback.SqliteDb/SqliteCursor— abiertos y cerrados dentro del propio hilo (víatry-with-resources). No compartas una conexión entre hilos; abre la tuya donde vayas a usarla.
Regla de oro del threading. Leer/escribir en la base de datos: hilo de trabajo. Tocar componentes de UI:
Component.onUI. Nunca al revés — acceder a componentes fuera del hilo de UI causa corrupción; bloquear la paint thread con I/O congela la app.
Recolecta antes de salir del hilo. El
SqliteCursoresAutoCloseabley está ligado a su conexión. No pases el cursor dentro delonUI. Materializa los datos (ej.: en unaList) en el hilo de trabajo y pasa solo la lista lista para la UI.
Ejemplo completo (copiar, pegar y ejecutar)
package com.exemplo;
import java.util.*; // List, ArrayList
import dev.crossfly.ui.*; // Window, Component
import dev.crossfly.ui.layout.*; // VerticalLayout
import dev.crossfly.sqlite.*; // SqliteDb, SqliteCursor
/** Pantalla principal ejecutable. Apunta el launcher (classname) y corre: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
new Thread(() ->
{
// --- thread de trabajo: I/O de la base de datos ---
List<String> nomes = new ArrayList<>();
try (SqliteDb db = SqliteDb.open("app.db");
SqliteCursor c = db.query("SELECT name FROM person ORDER BY name"))
{
while (c.next())
nomes.add(c.getString(0)); // recolecta ANTES de salir de la thread
}
// --- vuelve a la UI solo para actualizar componentes ---
Component.onUI(() ->
{
// aquí es seguro tocar componentes (setear lista, repaint, etc.)
preencheLista(nomes);
});
}).start();
}
/** Stub: actualiza aquí tus componentes de UI con los datos cargados. */
private void preencheLista(List<String> nomes)
{
// ej.: armar ítems en una lista, setear textos, repaint()...
}
}
El fragmento de abajo muestra solo el núcleo. Para ejecutarlo, colócalo en el esqueleto
MainWindowde arriba.
Fragmento mínimo
// verificado en la fuente: Component.onUI (Gdx.app.postRunnable), SqliteDb.query/cursor 0-based
import dev.crossfly.sqlite.*;
import dev.crossfly.ui.Component;
import java.util.*;
new Thread(() ->
{
// --- thread de trabajo: I/O de la base de datos ---
List<String> nomes = new ArrayList<>();
try (SqliteDb db = SqliteDb.open("app.db");
SqliteCursor c = db.query("SELECT name FROM person ORDER BY name"))
{
while (c.next())
nomes.add(c.getString(0)); // recolecta ANTES de salir de la thread
}
// --- vuelve a la UI solo para actualizar componentes ---
Component.onUI(() ->
{
// aquí es seguro tocar componentes (setear lista, repaint, etc.)
preencheLista(nomes);
});
}).start();
Profundiza
- Trabajo en background · Manejo de errores y logging
- Recetas hermanas: CRUD parametrizado · Transacción y escritura masiva