una tiempo thread tareas tarea studio peticiones hilos ejecutar como cierto cada asynctask asincronas android sqlite android-asynctask ormlite

android - tiempo - cómo asegurarse de que solo se ejecute una AsyncTask en segundo plano



thread android studio (4)

Creo que el problema al que se enfrenta es que está iniciando AsyncTask de una actividad. Su actividad extiende ORMLiteBaseActivity, lo que abre el helper (y con eso la base de datos) onCreate y lo cierra onDestroy. Cuando sale de la actividad y la tarea en segundo plano aún no ha terminado, cuando intenta escribir en la base de datos termina con una base de datos cerrada.

ORMLite maneja las sincronizaciones internamente y nunca he necesitado hacer bloques sincronizados con ella. Lo uso en todos mis proyectos que requieren una base de datos.

También para las otras respuestas, el error es una base de datos cerrada y no operaciones de escritura simultáneas, por lo que la sincronización no tiene sentido.

Tengo una clase, DownloadAndSave que se extiende desde AsyncTask . En su método doInBackground , recupera datos de una conexión http y guarda los datos usando OrmLite, pero también limpia las entradas antiguas de la base de datos. Entonces, algo como esto:

doInBackground() { clearDb(); dataList = fetchDataFromHttp(); saveToDb(dataList); }

Frecuentemente recibo una excepción DB:

intentar reabrir un objeto ya cerrado: SQLiteDatabase

en las funciones clearDb () y saveToDb ().

Y esto es malo ya que los datos antiguos de la llamada anterior de DownloadAndSave se mezclan con los nuevos datos de DownloadAndSave .

En mi opinión, necesito asegurarme de que cuando empiece un hilo, todas las otras bandas de la clase DownloadAndSave hayan terminado, o en otras palabras, necesito ejecutar como máximo una instancia de DownloadAndSave a la vez. Entonces la pregunta es: ¿cómo me aseguro de que solo se ejecute una instancia de DownloadAndSave en cualquier punto del tiempo?



Si usa la operación db en doInBackground, debería estar bloqueado db para un hilo.

public void insertToDb(){ SQliteDatabase db; ... db.beginTransaction(); ...//operation db.yieldIfContendedSafely(); db.setTransactionSuccessful(); db.endTransaction(); }


Opción 1 . Mover arriba:

clearDb(); dataList = fetchDataFromHttp(); saveToDb(dataList);

en una clase separada que se sincroniza con el objeto de la clase:

public class WorkerClass { private WorkerListener workerListener; public static interface WorkerListener { public void publishWorkProgress(String data); } public WorkerClass(WorkerListener workerListener) { this.workerListener = workerListener; } public void performWork() { synchronized (WorkerClass.class) { clearDb(); publish("Cleared DB"); dataList = fetchDataFromHttp(); publish("Got http data"); saveToDb(dataList); publish("There! saved!"); } } private void publish(String message) { if(workerListener != null) { workerListener.publishWorkProgress(message); } } }

Mientras desde tu actividad:

public class SampleActivity extends Activity { public void doTheThing() { new MyAsyncTask().execute(); } private static class MyAsyncTask extends AsyncTask<Void, String, Void> implements WorkerListener { @Override protected Void doInBackground(Void... params) { new WorkerClass(this).performWork(); return null; } @Override public void publishWorkProgress(String data) { publishProgress(data); } } }

Opción 2 : mover el código anterior a un servicio de intendencia:

public class WorkerIntentService extends IntentService { public WorkerIntentService() { super(null); } @Override protected void onHandleIntent(Intent intent) { clearDb(); dataList = fetchDataFromHttp(); saveToDb(dataList); } }

El uso de un IntentService garantiza que las tareas se ejecuten en serie.