我正在使用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)
答案 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
数据库采用相同的方法。如果AsyncTask
在ListView
需要数据时尚未完成,则会引发NullPointerException。
而是从ListView
的{{1}}方法填充onPostExecute
。这将确保数据库已完成复制。