2012-03-26 46 views
1

我得到一個零星的(約30倍)中的NullPointerException這行代碼。我不知道它來自哪裏以及如何預防它。sporadic 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: 線程正在以未捕獲的異常退出(group = 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) 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):在 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):在 java.lang.Thread.run(Thread.java:856)03-26 00:44:20.520: E/AndroidRuntime(6442):Caus編輯: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):at de.kialelem.trainer.ViewContentDatabaseListFragment $ processCursorTask.doInBackground(ViewContentDatabaseListFragment.java:48 ) 03-26 00:44:20.520:E/AndroidRuntime(6442):at de.kialelem.trainer.ViewContentDatabaseListFra gment $ 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個

+0

難道是因爲沒有正確的同步併發訪問'mDb'實例嗎? – assylias 2012-03-26 11:56:39

+0

我不確定,但是試着讓你的mDb易失 – 2012-03-26 12:00:04

回答

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

我遇到它了,我會試試你的解決方案 – Snake 2013-01-15 21:38:44

+0

我遇到它了,我會試試你的解決方案。你如何確定它的工作原理?我有預執行創建的對象,數據庫連接在線程中打開和關閉,並在後臺執行,我崩潰了 – Snake 2013-01-15 21:47:03

2

這並不完全清楚是什麼類的close()方法屬於。無論如何,您都撥打mDb.close()兩次:一次在close(),一次在doInBackground()

唯一的例外是發生內部SQLiteDatabase.closeDatabase(),所以它不造成mDbnull

作爲一般規則,不要打擾關閉數據庫。在應用程序啓動時打開一次,並在整個應用程序中重複使用相同的連接。由於SQLite的事務特性確保所有寫入操作都儘早提交到存儲中,所以您無法從關閉它中獲益。

編輯:好的,我現在可以看到mDb在每種情況下是不同的。無論如何,請聽我關於不關閉數據庫的建議,問題就會消失。

+0

我以前有過,但上面的代碼來自listFragment,在FragmentPager中使用。當我使用一個和相同的數據庫對象時,它會拋出異常,何時使用多個碎片。這是我嘗試解決的。而我沒有得到它,怎麼會發現,這個nullPointerException只是零星拋出。數據庫對象只爲AsyncTask創建。這意味着除了查詢方法外(除了循環將數據轉換爲數組之外,它實際上不超過一個rawQuery)之外,不會執行其他代碼。 – KarlKarlsom 2012-03-26 14:36:30

相關問題