2013-12-19 79 views
8

我正在使用SQLiteAssetHelper庫來處理我的應用程序數據庫操作,並且它幾乎適用於我測試過的每個手機。但是,有些用戶使用Android 2.3.3-2.3.7報告時,打開數據庫的調用發生崩潰。我懷疑這是由於第一次從資產文件夾複製數據庫時出現了一些問題(例如內部存儲空間不足)。SQLiteAssetHelper僅在某些設備上出現空指針異常

Helper類:

public class DbHelper extends SQLiteAssetHelper { 

    final static String DB_NAME="db"; 
    static final int DB_VERSION = 1307181213; 
    final Context context; 

    public DbHelper(Context c) { 
     super(c, DB_NAME, null, DB_VERSION); 
     this.context = c; 
     setForcedUpgradeVersion(DB_VERSION); 
    } 
} 

處理類(我設置一個計數器10秒後超時如果數據庫無法打開) :

public class DbHandlerDao { 

    private SQLiteDatabase database; 
private DbHelper dbHelper; 

public DbHandlerDao(Context context) { 
    dbHelper = new DbHelper(context); 
} 

public void open() throws SQLException { 
    boolean opened = false; 
    int timeout = 0; 
    while (!opened && timeout < 10000) { 
     try { 
      database = dbHelper.getReadableDatabase(); 
      opened = true; 
     } 
     catch (IllegalStateException e) { 
      timeout += 500; 
      try { 
       Thread.sleep(500); 
      } catch (Exception e2) { 

      } 
     } 
    } 
} 

public void close() { 
    dbHelper.close(); 
} 

調用類:

private class DbAsyncTask extends AsyncTask<Long, Void, Void> { 

     //... 

     @Override 
     protected Void doInBackground(Long... params) { 
      dataHandler.open(); 

例外:

java.lang.RuntimeException: An error occured while executing doInBackground() 
    at android.os.AsyncTask$3.done(AsyncTask.java:200) 
    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274) 
    at java.util.concurrent.FutureTask.setException(FutureTask.java:125) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581) 
    at java.lang.Thread.run(Thread.java:1019) 
Caused by: java.lang.NullPointerException 
    at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.getWritableDatabase(SQLiteAssetHelper.java:180) 
    at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.getReadableDatabase(SQLiteAssetHelper.java:257) 
    at com.example.DbHandlerDao.open(DbHandlerDao.java:25) 
    at com.example.SearchActivity$DbAsyncTask.doInBackground(SearchActivity.java:244) 
    at com.example.SearchActivity$DbAsyncTask.doInBackground(SearchActivity.java:1) 
    at android.os.AsyncTask$2.call(AsyncTask.java:185) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306) 
+0

我在運行Android 4.3和4.4的幾款設備上遇到了同樣的錯誤。奇怪的是我無法一直重現它。 – Ben

+0

我將它作爲github項目本身的問題發佈,因爲它幾乎可以保證是庫的問題 - 標準SQLiteOpenHelper沒有這個問題。似乎其他人也有這個問題:https://github.com/jgilfelt/android-sqlite-asset-helper/issues/23 – anddev84

+2

謝謝,好主意。但經過一番調查後,我意識到這是我自己的錯誤。長話短說,我在一個活動的'onCreate'方法中調用'AsyncTask'來複制數據庫,然後嘗試使用同一個數據庫填充'ListView'。事實證明,只有當我幸運並且後臺任務在'ListView'需要數據庫之前完成時才起作用! – Ben

回答

0

可能用戶已清除存儲空間或者他們沒有SD卡?

可能是什麼零星的崩潰。

** 您是否實現了oncreate和onupgrade方法?

我使用打開的幫助程序。所以我從來沒有打開數據庫的麻煩。

public class RidesDatabaseHandler extends SQLiteOpenHelper { 

...

// Creating Tables 
@Override 
public void onCreate(SQLiteDatabase db) { 
    String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_RIDES + "(" 
      + KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT," 
      + KEY_DESCRIPTION + " TEXT," + KEY_BOUNDS_NELAT + " TEXT," 
      + KEY_BOUNDS_NELONG + " TEXT," + KEY_BOUNDS_SWLAT + " TEXT," 
      + KEY_BOUNDS_SWLONG + " TEXT," + KEY_RESRAWID + " TEXT," 
      + KEY_RESDRAWABLEID + " TEXT," + KEY_PATH + " TEXT," 
      + " CONSTRAINT UNQ_" + KEY_PATH + " UNIQUE (" + KEY_PATH 
      + ") ON CONFLICT ABORT)"; 

    // VERSION 43 ADDS THE KEY_DATE_UPDATE COLUMN 
    CREATE_CONTACTS_TABLE += " , " + KEY_DATE_UPDATE + " INTEGER DEFAULT 0"; 

    db.execSQL(CREATE_CONTACTS_TABLE); 
} 

// Upgrading database 
@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 

    int upgradeTo = oldVersion + 1; 
    while (upgradeTo <= newVersion) { 
     switch (upgradeTo) { 
     // update old resrawid's to constants 
     // this was caused when I saved R values in the database 
     // and then later realized they would change. 
     // the old resrawid is changed to a constant. 
     case 42: 
      ContentValues values; 
      @SuppressWarnings("unused") 
      // used for debugging so I can see the value of the update. 
      int res; 
      int rs; 
      rs = 2130968576; 
      values = new ContentValues(); 
      values.put(
        KEY_RESRAWID, 
        com.gosylvester.bestrides.ImageTextListViewActivity.SAMPLE_DRAGON); 
      res = db.update(TABLE_RIDES, values, KEY_RESRAWID + " = ?", 
        new String[] { String.valueOf(rs) }); 

      rs = 2130968577; 
      values = new ContentValues(); 
      values.put(
        KEY_RESRAWID, 
        com.gosylvester.bestrides.ImageTextListViewActivity.SAMPLE_M119); 
      res = db.update(TABLE_RIDES, values, KEY_RESRAWID + " = ?", 
        new String[] { String.valueOf(rs) }); 

      rs = 2130968578; 
      values = new ContentValues(); 
      values.put(
        KEY_RESRAWID, 
        com.gosylvester.bestrides.ImageTextListViewActivity.SAMPLE_MEDINA); 
      res = db.update(TABLE_RIDES, values, KEY_RESRAWID + " = ?", 
        new String[] { String.valueOf(rs) }); 
      break; 
     case 43: 
      // new column added for last_viewed. 
      db.execSQL(VERSION_43_ALTER); 
      break; 

     case 44: 
      // new index on KEY_DATE_UPDATE DESC 
      db.execSQL(VERSION_44_CREATE_INDEX); 
     } 
     upgradeTo++; 
    } 

好運

0

這個問題並沒有一個公認的答案,即使OP表示,它在評論中解決。因此,這裏的答案:

不要嘗試將數據庫與AsyncTask被稱爲從一個方法(如onCreate),然後嘗試同樣的方法用數據填充ListView從數據庫中拷貝。如果AsyncTaskListView需要數據時尚未完成,則會引發NullPointerException。

取而代之,從AsyncTaskonPostExecute方法填充ListView。這將確保數據庫已完成複製。