случайное исключение NullPointerException, несмотря на то, что объект не равен нулю - PullRequest
1 голос
/ 26 марта 2012

Я получаю спорадическое (1 из ~ 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): в java.util.concurrent.FutureTask $ Sync.innerSetException (FutureTask.java:273) 03-26 00: 44: 20.520: E / AndroidRuntime (6442): в java.util.concurrent.FutureTask.setException (FutureTask.java:124)
03-26 00: 44: 20.520: E / AndroidRuntime (6442): в java.util.concurrent.FutureTask $ Sync.innerRun (FutureTask.java:307)
03-26 00: 44: 20.520: E / AndroidRuntime (6442): в java.util.concurrent.FutureTask.run (FutureTask.java:137)
03-26 00: 44: 20.520: E / AndroidRuntime (6442): в android.os.AsyncTask $ SerialExecutor $ 1.run (AsyncTask.java:208)
03-26 00: 44: 20.520: E / AndroidRuntime (6442): в java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1076) 03-26 00: 44: 20.520: E / AndroidRuntime (6442): в java.util.concurrent.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.java:569) 03-26 00: 44: 20.520: E / AndroidRuntime (6442): в 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): в android.database.sqlite.SQLiteDatabase.closeDatabase (SQLiteDatabase.java:1156) 03-26 00: 44: 20.520: E / AndroidRuntime (6442): в android.database.sqlite.SQLiteDatabase.close (SQLiteDatabase.java:1105) 03-26 00: 44: 20.520: E / AndroidRuntime (6442): в de.kialelem.trainer.DbHelper.close (DbHelper.java:676) 03-26 00: 44: 20.520: E / AndroidRuntime (6442): в de.kialelem.trainer.ViewContentDatabaseListFragment $ processCursorTask.doInBackground (ViewContentDatabaseListFragment.java:48) 03-26 00: 44: 20.520: E / AndroidRuntime (6442): в de.kialelem.trainer.ViewContentDatabaseListFragment $ processCursorTask.doInBackground (ViewContentDatabaseListFragment.java:1) 03-26 00: 44: 20.520: E / AndroidRuntime (6442): в android.os.AsyncTask $ 2.call (AsyncTask.java:264) 03-26 00: 44: 20.520: E / AndroidRuntime (6442): в java.util.concurrent.FutureTask $ Sync.innerRun (FutureTask.java:305)
03-26 00: 44: 20.520: E / AndroidRuntime (6442): ... еще 5

Ответы [ 2 ]

2 голосов
/ 26 марта 2012

Не совсем понятно, к какому классу относится ваш close() метод, указанный выше. В любом случае вы звоните mDb.close() дважды: один раз на close() и один раз на doInBackground().

Исключение происходит внутри SQLiteDatabase.closeDatabase(), поэтому не вызвано тем, что mDb является null.

Как правило, не беспокойтесь о закрытии базы данных. Откройте его один раз при запуске приложения и повторно используйте одно и то же соединение во всем приложении. Вы не получите никакой выгоды от его закрытия, так как транзакционный характер SQLite гарантирует, что все записи фиксируются в хранилище при первой же возможности.

РЕДАКТИРОВАТЬ : ОК, теперь я вижу, что mDb в каждом случае отличается. В любом случае, примите мой совет не закрывать БД, и проблема исчезнет.

1 голос
/ 08 июня 2012

Нашел решение: проблема заключалась в том, что объект DbHelper был создан в потоке пользовательского интерфейса, но закрыт в рабочем потоке 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);
}
}
...