Android中的SQLite错误插入

时间:2014-03-27 18:43:24

标签: android sqlite android-asynctask

我需要每隔30秒运行以下代码。

public void push(Context context,String codigoEvento){
    SessionManager manager = new SessionManager();
    folioEvento = manager.getValue(context,"folioEvento");
    nombreCliente = manager.getValue(context,"nombreCliente");
    nombreUser = manager.getValue(context, "nombreUser");
    hashUser = manager.getValue(context, "hashUsuario");
    if(!(folioEvento.equals("") || nombreCliente.equals(""))){
        Connection cn = new Connection();
        if(cn.isNetworkAvailable(context)){
        String ids = "";
        SQLiteDatabase db = TicketsBaseDatos.getInstance(context).getWritableDatabase();
        Cursor c = db.rawQuery("SELECT inscripcion_id FROM Inscripcion WHERE validado=1 and sincronizado = 1",null);
        if (c.moveToFirst()) {
             do {
                ids += c.getString(0)+",";
                ContentValues valores = new ContentValues();
                valores.put("sincronizado","1");
                String[] args = new String[]{c.getString(0), codigoEvento};
                db.update("Inscripcion", valores, "inscripcion_id=? AND codigo_evento=?", args);
             } while(c.moveToNext());
        }
        db.close();
        c.close();
        JSONParser jParser = new JSONParser();
        JSONObject json = jParser.getJSONFromUrl(Config.URL_BASE+nombreCliente+"/"+Config.URL_PUSH+nombreUser+"/"+hashUser+"/"+folioEvento+"/"+ids);
        try {
              String status = json.getString("status");
              if(status.equals("1")){
                  System.out.println("BIEN");
              }
              else{
                  System.out.println("MAL");
              }
          } catch (JSONException e) {
            e.printStackTrace();
          }
        }
    }
}

之后,用户将能够从Web服务下载数据,是以下代码,这个任务,我是在AsyncTask中做的:

public void sincronizarBD(Context context, String codigoEvento) {
    Connection cn = new Connection();
    if(cn.isNetworkAvailable(context)){
        SessionManager manager = new SessionManager();
        folioEvento = manager.getValue(context,"folioEvento");
        nombreCliente = manager.getValue(context,"nombreCliente");
        codigoUser = manager.getValue(context,"codigoUser");
        nombreUser = manager.getValue(context, "nombreUser");
        hashUser = manager.getValue(context, "hashUsuario");
        JSONParser jParser = new JSONParser();
        BaseDeDatos nueva = new BaseDeDatos();
        try {
              do{
                  int recorrido = 0;
                  JSONObject json = jParser.getJSONFromUrl(Config.URL_BASE+nombreCliente+"/"+Config.URL_DESCARGA_BD+nombreUser+"/"+hashUser+"/"+folioEvento+"/"+start+"/"+cantidad);
                  JSONArray array = json.getJSONArray("Inscripciones");
                  for (int i = 0; i < array.length(); i++) {
                          recorrido++;
                          JSONObject rowParticipante = array.getJSONObject(i);
                              SQLiteDatabase db = TicketsBaseDatos.getInstance(context).getWritableDatabase();
                              System.out.println(i);
                              ContentValues nuevoRegistro = new ContentValues();
                              nuevoRegistro.put("hash", rowParticipante.getString("hash"));
                              nuevoRegistro.put("codigo_evento", rowParticipante.getString("codigo_evento"));
                              nuevoRegistro.put("ticket",rowParticipante.getString("ticket"));
                              nuevoRegistro.put("nombre",rowParticipante.getString("nombre"));
                              nuevoRegistro.put("inscripcion_id",rowParticipante.getString("inscripcion_id"));
                              nuevoRegistro.put("validado", rowParticipante.getInt("validado"));
                              nuevoRegistro.put("sincronizado", 0);
                              nuevoRegistro.put("numero", rowParticipante.getString("numero"));
                              nuevoRegistro.put("categoria", rowParticipante.getString("categoria"));
                              nuevoRegistro.put("codigo_usuario", codigoUser);
                              nuevoRegistro.put("rut", rowParticipante.getString("rut_clean"));
                              nuevoRegistro.put("talla", rowParticipante.getString("talla"));
                              System.out.println("Guardado con exito");
                              db.insert("Inscripcion", null, nuevoRegistro);
                              nuevoRegistro.clear();
                              db.close();
                  }
                  if(recorrido>0){
                      start = start + cantidad;
                  } else {
                      continuar = false;
                  }
              }while(continuar == true);
      } catch (JSONException e) {
        e.printStackTrace();
      }
    }
}

这是我做的错误&#34;拉&#34;同时下载&#34; sincronizarBD&#34;抛出我的错误。

03-28 02:30:14.547: E/AndroidRuntime(16117): FATAL EXCEPTION: AsyncTask #3

03-28 02:30:14.547:E / AndroidRuntime(16117):java.lang.RuntimeException:执行doInBackground()时发生错误 03-28 02:30:14.547:E / AndroidRuntime(16117):在android.os.AsyncTask $ 3.done(AsyncTask.java:299) 03-28 02:30:14.547:E / AndroidRuntime(16117):at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352) 03-28 02:30:14.547:E / AndroidRuntime(16117):at java.util.concurrent.FutureTask.setException(FutureTask.java:219) 03-28 02:30:14.547:E / AndroidRuntime(16117):at java.util.concurrent.FutureTask.run(FutureTask.java:239) 03-28 02:30:14.547:E / AndroidRuntime(16117):at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 03-28 02:30:14.547:E / AndroidRuntime(16117):at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:573) 03-28 02:30:14.547:E / AndroidRuntime(16117):at java.lang.Thread.run(Thread.java:856) 03-28 02:30:14.547:E / AndroidRuntime(16117):引起:java.lang.IllegalStateException:尝试重新打开已关闭的对象:SQLiteDatabase:/data/data/com.androidaz.scanner/databases / Eventrid 03-28 02:30:14.547:E / AndroidRuntime(16117):在android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55) 03-28 02:30:14.547:E / AndroidRuntime(16117):在android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1543) 03-28 02:30:14.547:E / AndroidRuntime(16117):在android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1445) 03-28 02:30:14.547:E / AndroidRuntime(16117):at com.androidaz.scanner.Sincronizacion.sincronizarBD(Sincronizacion.java:73) 03-28 02:30:14.547:E / AndroidRuntime(16117):at com.androidaz.scanner.MenuEvento $ sincronizarBD.doInBackground(MenuEvento.java:205) 03-28 02:30:14.547:E / AndroidRuntime(16117):at com.androidaz.scanner.MenuEvento $ sincronizarBD.doInBackground(MenuEvento.java:1) 03-28 02:30:14.547:E / AndroidRuntime(16117):在android.os.AsyncTask $ 2.call(AsyncTask.java:287) 03-28 02:30:14.547:E / AndroidRuntime(16117):at java.util.concurrent.FutureTask.run(FutureTask.java:234)

我的SQLhelper

public class TicketsBaseDatos extends SQLiteOpenHelper {

String sqlCreateBDEvent = "CREATE TABLE IF NOT EXISTS Evento  (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, codigo_evento TEXT , nombre TEXT, codigo_usuario TEXT, folio TEXT, nombre_cliente TEXT)";
String sqlCreateBDInscripcion = "CREATE TABLE IF NOT EXISTS Inscripcion (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, hash TEXT, codigo_evento TEXT, ticket TEXT, nombre TEXT, inscripcion_id TEXT, validado int, sincronizado int, numero TEXT, categoria TEXT, codigo_usuario TEXT, rut TEXT, talla TEXT)";
private static TicketsBaseDatos sInstance;
public static TicketsBaseDatos getInstance(Context context) {
    if (sInstance == null) {
      sInstance = new TicketsBaseDatos(context.getApplicationContext());
    }
    return sInstance;
  }


public TicketsBaseDatos(Context ctx) {
    super(ctx, "Eventrid", null, 1);
}

}

要运行一段时间我的推动动作,占用计时器:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Sincronizacion s = new Sincronizacion();
    SessionManager ss = new SessionManager();
    try{
        codigoEvento = ss.getValue(this,"codigoEvento");
        folioEvento = ss.getValue(this,"folioEvento");
        nombreCliente = ss.getValue(this,"nombreCliente");
    if((codigoEvento != null) && (!codigoEvento.equals("") && (folioEvento != null) && (!folioEvento.equals("") && (nombreCliente != null) && (!nombreCliente.equals(""))))){
            s.push(getApplicationContext(), codigoEvento);
            s.pull(getApplicationContext(), codigoEvento);
            Toast.makeText(this, "PULL Y PUSH", Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(this, "Push sin codigo", Toast.LENGTH_SHORT).show();
        }
    }catch(Exception e){
        Toast.makeText(this, "NO HAY CODIGOS", Toast.LENGTH_SHORT).show();
    }
    return START_STICKY;
}


cronTimerTask = new TimerTask() {
     @Override
     public void run() {
         startService(new Intent(getBaseContext(), CronPush.class));
     }
};
cron = new Timer();
cron.schedule(cronTimerTask, 0, 30000);

因为我抛出了这个错误?任何解决方案?

2 个答案:

答案 0 :(得分:0)

抛出此异常是因为您已关闭数据库连接,然后尝试对其执行其他操作,代码中的问题就在这一行:

for(..){
    SQLiteDatabase db = TicketsBaseDatos.getInstance(context).getWritableDatabase();                           
    ...
    db.insert("Inscripcion", null, nuevoRegistro);
    nuevoRegistro.clear();
    db.close();
}

你不应该每次在你的for循环中询问数据库,它更好(和更快)只请求它一次并在最后关闭它像这样:

SQLiteDatabase db = TicketsBaseDatos.getInstance(context).getWritableDatabase();                           
for(..){
            ...
    db.insert("Inscripcion", null, nuevoRegistro);
    nuevoRegistro.clear();
}
db.close();

答案 1 :(得分:0)

您正在为您的SQLiteOpenHelper使用Singleton,如果您想要在多个线程中访问数据库,这是一个好主意,但如果您偶尔关闭它,则不是。虽然一个线程可能会关闭数据库(就像你的推送方法),但是另一个线程(比如你的AsyncTask)试图使用相同的 - 现在关闭的 - 数据库。

有两种方法可以解决这个问题:

  1. 不要关闭数据库,除非不再需要它。对于ContentProvider(参见When should I call close() on SQLiteOpenHelper used by ContentProvider),或者对于活动或片段,这可能永远不会出现在onDestroy()中。
  2. 跟踪close和open语句,只有在所有线程完成它们应该执行的操作后才关闭它。有例如这个https://github.com/d4rxh4wx/MultiThreadSQLiteOpenHelper或者您可以使用Locks添加自己的同步机制(例如ReentrantReadWriteLock)。
  3. Google for SQLiteOpenHelper多线程,你会发现很多关于你所面临问题的帖子。