我在这行代码中得到零星的(大约30次)NullPointerException。我不知道它来自何处以及如何防止它。
public void close() {
if (mDb!=null)
mDb.close();
}
mDb是一个SQliteDatabase对象,而Close函数是在Helper类中实现的。
我在做什么:我想在SQliteDatabase中使用AsyncTask处理复杂查询。 这是AsyncTask的代码:
private class processCursorTask extends AsyncTask<Integer[], Void, Dataset[]> {
private DbHelper mDb;
processCursorTask(DbHelper db) {
super();
mDb=db;
}
@Override
protected Dataset[] doInBackground(Integer... args) {
Dataset[] res=mDb.getCursorFiltered(args);
mDb.close();
return res;
}
protected void onPostExecute(Dataset[] result) {
setListView(result);
}
}
我在这里创建了这个AsyncTask(来自ListFragment):
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
new processCursorTask(new DbHelper(this.getActivity()), mBaseDivision, mBaseValue, mSortOrder, mSortDir).execute();
}
03-26 00:44:20.489:E / SqliteDatabaseCpp(6442):sqlite3_close(0x3b2278) 失败:27 03-26 00:44:20.520:W / dalvikvm(6442):threadid = 12: 线程退出与未捕获的异常(组= 0x40a691f8)03-26 00:44:20.520:E / AndroidRuntime(6442):致命异常:AsyncTask#2
03-26 00:44:20.520:E / AndroidRuntime(6442): java.lang.RuntimeException:执行时发生错误 doInBackground()03-26 00:44:20.520:E / AndroidRuntime(6442): 在android.os.AsyncTask $ 3.done(AsyncTask.java:278)
03-26 00:44:20.520:E / AndroidRuntime(6442):at java.util.concurrent.FutureTask中$ Sync.innerSetException(FutureTask.java:273) 03-26 00:44:20.520:E / AndroidRuntime(6442):at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
03-26 00:44:20.520:E / AndroidRuntime(6442):at java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:307)
03-26 00:44:20.520:E / AndroidRuntime(6442):at java.util.concurrent.FutureTask.run(FutureTask.java:137)
03-26 00:44:20.520:E / AndroidRuntime(6442):at android.os.AsyncTask $ SerialExecutor $ 1.run(AsyncTask.java:208)
03-26 00:44:20.520:E / AndroidRuntime(6442):at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) 03-26 00:44:20.520:E / AndroidRuntime(6442):at java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:569) 03-26 00:44:20.520:E / AndroidRuntime(6442):at java.lang.Thread.run(Thread.java:856)03-26 00:44:20.520: E / AndroidRuntime(6442):引起:java.lang.NullPointerException
03-26 00:44:20.520:E / AndroidRuntime(6442):at android.database.sqlite.SQLiteDatabase.closeDatabase(SQLiteDatabase.java:1156) 03-26 00:44:20.520:E / AndroidRuntime(6442):at android.database.sqlite.SQLiteDatabase.close(SQLiteDatabase.java:1105) 03-26 00:44:20.520:E / AndroidRuntime(6442):at de.kialelem.trainer.DbHelper.close(DbHelper.java:667)03-26 00:44:20.520:E / AndroidRuntime(6442):at de.kialelem.trainer.ViewContentDatabaseListFragment $ processCursorTask.doInBackground(ViewContentDatabaseListFragment.java:48) 03-26 00:44:20.520:E / AndroidRuntime(6442):at de.kialelem.trainer.ViewContentDatabaseListFragment $ processCursorTask.doInBackground(ViewContentDatabaseListFragment.java:1) 03-26 00:44:20.520:E / AndroidRuntime(6442):at android.os.AsyncTask $ 2.call(AsyncTask.java:264)03-26 00:44:20.520:E / AndroidRuntime(6442):at java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:305)
03-26 00:44:20.520:E / AndroidRuntime(6442):... 5 more
答案 0 :(得分:2)
上述close()
方法所属的课程并不完全清楚。无论如何,您要拨打mDb.close()
两次:一次在close()
,一次在doInBackground()
。
例外情况发生在SQLiteDatabase.closeDatabase()
内,因此mDb
null
引起的不是。
作为一般规则,不要打扰关闭数据库。在应用启动时打开一次,并在整个应用中重复使用相同的连接。关闭它没有任何好处,因为SQLite的事务性质确保所有写入都尽可能早地提交到存储。
编辑:好的,我现在可以看到mDb
在每种情况下都不同。无论如何,请听取我关于不关闭数据库的建议,问题就会消失。
答案 1 :(得分:1)
找到解决方案: 问题是DbHelper对象是在UI线程上创建的,但在asyncTask工作线程中关闭。 将.close()移动到onPostExecute()方法后,异常消失了。
private class processCursorTask extends AsyncTask<Integer[], Void, Dataset[]> {
private DbHelper mDb;
processCursorTask(DbHelper db) {
super();
mDb=db;
}
@Override
protected Dataset[] doInBackground(Integer... args) {
Dataset[] res=mDb.getCursorFiltered(args);
return res;
}
protected void onPostExecute(Dataset[] result) {
mDb.close();
setListView(result);
}
}