更新时间:2023-11-19 14:28:52
这个问题并没有一个公认的答案,即使OP表示,它解决了评论。因此,这里的答案是:
不要试图复制数据库的的AsyncTask
这是从方法称为(如的onCreate
),然后尝试在相同的方法从数据库中填充的ListView
数据。如果的AsyncTask
并没有被当时的的ListView
需要那么一个NullPointerException异常将被提出的数据完成了。
相反,填充的ListView
从的 onPostExecute
方法的AsyncTask
。这将确保数据库完成复制
I am using SQLiteAssetHelper library to deal with my App DB operations and it's working fine for almost every phone I've tested with. However some users with Android 2.3.3 - 2.3.7 report crashes when a call to open the db is made. I suspect this is due to some issue occuring the first time the db is being copied from the asset folder (such as insufficient space in the internal storage).
Helper class:
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);
}
}
Handler Class (I set a counter to timeout after 10s if db cannot be opened) :
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();
}
Calling class:
private class DbAsyncTask extends AsyncTask<Long, Void, Void> {
//...
@Override
protected Void doInBackground(Long... params) {
dataHandler.open();
Exception:
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)
This question didn't have an accepted answer even though the OP indicated that it was solved in the comments. So here is the answer:
Don't try to copy the database with an AsyncTask
that is called from a method (such as onCreate
) and then try to populate a ListView
with data from the database in the same method. If the AsyncTask
has not finished by the time the ListView
needs the data then a NullPointerException will be raised.
Instead, populate the ListView
from the onPostExecute
method of the AsyncTask
. That will ensure that the database has finished copying.