1

このコード行で散発的な(約30回のうち1回)NullPointerExceptionが発生しています。そして、それがどこから来たのか、そしてそれをどのように防ぐのか、私にはわかりません。

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

mDbはSQliteDatabaseオブジェクトであり、Close関数はHelperクラスに実装されています。

私がしていること:AsyncTaskを使用してそのSQliteDatabaseで複雑なクエリを処理したいと思います。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):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):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):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-2600: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詳細

4

2 に答える 2

2

close()上記のメソッドがどのクラスに属しているかは完全には明らかではありません。いずれにせよ、あなたは2回電話をかけています。1mDb.close()回はでclose()、もう1回はでdoInBackground()

例外は内部SQLiteDatabase.closeDatabase()で発生しているので、それはあなたの存在が原因ではありませんmDbnull

原則として、わざわざデータベースを閉じないでください。アプリの起動時に一度開き、アプリ全体で同じ接続を再利用します。SQLiteのトランザクションの性質により、すべての書き込みがとにかくできるだけ早い機会にストレージにコミットされるため、これを閉じることによるメリットはありません。

編集mDb:OK、それぞれの場合が異なることがわかります。いずれにせよ、DBを閉じないことについての私のアドバイスを参考にしてください。そうすれば、問題は解決します。

于 2012-03-26T11:58:51.770 に答える
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);
}
}
于 2012-06-07T21:38:08.860 に答える