SQLiteAssetHelper仅在某些设备上出现NullPointerException

时间:2013-12-19 23:04:54

标签: android sqlite

我正在使用SQLiteAssetHelper库来处理我的App数据库操作,它几乎适用于我测试过的每部手机。但是,当打开数据库的调用时,一些使用Android 2.3.3 - 2.3.7的用户会报告崩溃。我怀疑这是因为第一次从资产文件夹复制数据库时出现了一些问题(例如内部存储空间不足)。

助手类:

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);
    }
}

处理程序类(如果无法打开db,我会在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)

2 个答案:

答案 0 :(得分:0)

用户可能已清理存储空间,或者他们没有SD卡?

可能会发生零星的撞车事故。

** 您是否实施了oncreate和onupgrade方法?

我使用open helper。所以我从来没有打开数据库的麻烦。

 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++;
    }

祝你好运

答案 1 :(得分:0)

即使OP表明在评论中已经解决了这个问题,但这个问题还没有得到公认答案。所以这就是答案:

请勿尝试使用从方法(例如AsyncTask)调用的onCreate复制数据库,然后尝试使用来自该方法的数据填充ListView数据库采用相同的方法。如果AsyncTaskListView需要数据时尚未完成,则会引发NullPointerException。

而是从ListView的{​​{1}}方法填充onPostExecute。这将确保数据库已完成复制。