سؤال

Im getting a sporadic (1 out of ~30 times) NullPointerException in this line of Code. and I have no Idea where it comes from and how to prevent it.

public void close() {
    if (mDb!=null)
        mDb.close();
}

mDb is a SQliteDatabase Object and the Close function is implemented into a Helper class.

What I am doing: I want to handle a complex query in that SQliteDatabase with an AsyncTask. Here is the code of the 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);
    }
}

And I am creating this AsyncTask here (from a 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) failed: 27 03-26 00:44:20.520: W/dalvikvm(6442): threadid=12: thread exiting with uncaught exception (group=0x40a691f8) 03-26 00:44:20.520: E/AndroidRuntime(6442): FATAL EXCEPTION: AsyncTask #2
03-26 00:44:20.520: E/AndroidRuntime(6442): java.lang.RuntimeException: An error occured while executing doInBackground() 03-26 00:44:20.520: E/AndroidRuntime(6442): at 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): Caused by: 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:676) 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

هل كانت مفيدة؟

المحلول 2

Found the solution: The Problem was that the DbHelper Object was created on the UI thread but closed in the asyncTask worker thread. After I moved the .close() into the onPostExecute() method the exception disappeared.

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

نصائح أخرى

It's not entirely clear what class your close() method above belongs to. In any event, you are calling mDb.close() twice: once in close() and once in doInBackground().

The exception is happening inside SQLiteDatabase.closeDatabase(), so it's not caused by your mDb being null.

As a general rule, don't bother closing the database. Open it once on app startup, and reuse the same connection throughout your app. You get no benefit from closing it, since SQLite's transactional nature ensures all writes are committed to storage at the earliest opportunity anyway.

EDIT: OK, I can see now that the mDb in each case is different. In any event, take my advice about not closing the DB, and the problem will go away.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top