2017-07-27 96 views
0

正在创建超过20k条目的医学词典。在保存此数据以供脱机使用时,由于数据库锁定导致应用程序崩溃。我该如何解决这个问题?执行批量插入时锁定的Android Sqlite数据库

我插入功能

public static void saveWords(AppCompatActivity appCompatActivity, Context context, JSONArray response) { 
     DbHelper helper = new DbHelper(context); 


     ProgressDialog progressDialog = new ProgressDialog(context); 
     progressDialog.setMessage("Finalising..."); 
     progressDialog.setCancelable(false); 
     progressDialog.show(); 

     db = helper.getWritableDatabase(); 
     db.beginTransaction(); 
     try { 
      ContentValues contentValues = new ContentValues(); 
      for (int i = 0; i < response.length(); i++) { 
       JSONObject object = response.getJSONObject(i); 
       String wordId = object.getString("wordid"); 
       String category = object.getString("category"); 
       String word = object.getString("word"); 
       String meaning = object.getString("meaning"); 
       String letter = object.getString("letter"); 

       if (!wordExists(context, wordId)) { 
        contentValues.put(DbConstants.WORD_ID, wordId); 
        contentValues.put(DbConstants.CATEGORY, category); 
        contentValues.put(DbConstants.WORD, word); 
        contentValues.put(DbConstants.MEANING, meaning); 
        contentValues.put(DbConstants.LETTER, letter); 
        contentValues.put(DbConstants.STATUS, "0"); 

        db.insert(DbConstants.TABLE_WORDS, null, contentValues); 
       } 
      } 
      db.setTransactionSuccessful(); 

     } catch (JSONException e) { 
      e.printStackTrace(); 
     } finally { 
      db.endTransaction(); 
      progressDialog.dismiss(); 
      appCompatActivity.recreate(); 
     } 

    } 

wordExists方法:

private static boolean wordExists(Context context, String wordId) { 
     DbHelper helper = new DbHelper(context); 
     db = helper.getWritableDatabase(); 
     String[] columns = {DbConstants.WORD_ID}; 
     String whereClause = DbConstants.WORD_ID + " = ? "; 
     String whereArgs[] = {wordId}; 

     Cursor cursor = db.query(DbConstants.TABLE_WORDS, columns, whereClause, whereArgs, null, null, null, null); 
     if (cursor.getCount() > 0) { 
      cursor.close(); 
      return true; 
     } 
     cursor.close(); 
     return false; 

    } 

我似乎无法明白的地方问题。

回答

1

后的某个时候我已经得到了解。我的问题是,我试图在数据库已经很忙时重新打开数据库。其实是我的工作搞砸了wordExists方法。这是我的新代码:

public static void saveWords(AppCompatActivity appCompatActivity, Context context, JSONArray response) { 
     DbHelper helper = new DbHelper(context); 


     ProgressDialog progressDialog = new ProgressDialog(context); 
     progressDialog.setMessage("Finalising..."); 
     progressDialog.setCancelable(false); 
     progressDialog.show(); 

     db = helper.getWritableDatabase(); 
     db.beginTransaction(); 
     try { 
      ContentValues contentValues = new ContentValues(); 
      for (int i = 0; i < response.length(); i++) { 
       JSONObject object = response.getJSONObject(i); 
       String wordId = object.getString("wordid"); 
       String category = object.getString("category"); 
       String word = object.getString("word"); 
       String meaning = object.getString("meaning"); 
       String letter = object.getString("letter"); 

       String[] columns = {DbConstants.WORD_ID}; 
       String whereClause = DbConstants.WORD_ID + " = ? "; 
       String whereArgs[] = {wordId}; 

       Cursor cursor = db.query(DbConstants.TABLE_WORDS, columns, whereClause, whereArgs, null, null, null, null); 
       if (cursor.getCount() <= 0) { 
        contentValues.put(DbConstants.WORD_ID, wordId); 
        contentValues.put(DbConstants.CATEGORY, category); 
        contentValues.put(DbConstants.WORD, word); 
        contentValues.put(DbConstants.MEANING, meaning); 
        contentValues.put(DbConstants.LETTER, letter); 
        contentValues.put(DbConstants.STATUS, "0"); 

        db.insert(DbConstants.TABLE_WORDS, null, contentValues); 

       } 
       cursor.close(); 
      } 
      db.setTransactionSuccessful(); 

     } catch (JSONException e) { 
      e.printStackTrace(); 
     } finally { 
      db.endTransaction(); 
      progressDialog.dismiss(); 
      appCompatActivity.recreate(); 
     } 


     } 
    } 

我正在尝试建立新的连接,当上一个连接仍在进程中时。在同一个事务中,数据库连接应该建立一次。

0

确保以下几点存储离线数据:

  • 保存缓存文件
  • 传递一个超时值作为一个选项
  • 启用离线功能
+1

完全脱离话题 –

0

首先,DbHelper helper = new DbHelper(context)是昂贵的类。是否有任何用例需要为每次调用wordExists重新创建一个实例。正如你所说,有超过20K的条目,所以有超过20K实例一次又一次地创建...

第二,如果我没有错,这个函数db.setTransactionSuccessful();将关闭数据库。而且你知道,当db在结束事务之前关闭时,它会导致错误。

它应该是这样的

finally { 
     db.endTransaction(); 
     db.setTransactionSuccessful(); 
     progressDialog.dismiss(); 
     appCompatActivity.recreate(); 
    }