2012-01-02 135 views
0

我有一個具有SimpleCursorAdapter作爲字段的類。該適配器用於提供具有viewBinder的列表視圖。ListView SimpleCursorAdapter異步更新

我有一個異步任務,運行它將一個條目添加到數據庫,然後更新遊標。

在測試中,如果我點擊太快上運行的異步過程中的按鈕,我得到一個錯誤:

java.lang.RuntimeException: An error occured while executing doInBackground() 
... 
Caused by: java.lang.IllegalStateException: database [path_to_my_db] already closed 

代碼工作完美 - 除非......用戶點擊保存按鈕迅速繼任...我是新手,所以任何輸入將不勝感激!

這裏是什麼,我試圖做一個精簡版:

public class MyActivity extends Activity { 

    private DatabaseConnector connector; // this is my class for managing SQLite 
    private SimpleCursorAdapter adapter; 

    .... 

    @Override 
    public void onCreate(Bundle savedInstanceState){ 

     ... 

     myListView = (ListView)findViewById(R.id.my_list_view); 
     String[] = new String{"This", "part", "is", "working"}; 
     int[] to = new int[] {1,2,3,4}; // again, this is working... 

     adapter = new SimpleCursorAdapter(this, R.layout.my_list_item_row, null, from, to); 
     adapter.setViewBinder(new ViewBinder(){ 
      ... // this is all working 
      ... // the viewBinder is for custom date formatting... again, all works 
     }); 

     myListView.setAdapter(adapter); 

    } 

    private class MyAsyncTask extends AsyncTask<Context, Void, ExerciseInstanceViewModel>{ 

     MyViewModel vm; // this viewModel has a cursor member... 

     public MyAsyncTask([variables-all-working]){ 

     } 

     @Override 
     protected MyViewModel doInBackground(Context... params) { 

      connector = new DatabaseConnector(MyActivity.this); 
      connector.open(); // TODO: Getting 'did not close database error here...' 

      vm = connector.runMethodThatIncludesCursorInReturnType([input-paramters-working]); 

      return vm; 

      } 

     // use the cursor returned from the doInBackground method 
     @Override 
     protected void onPostExecute(MyViewModel result){ 

      super.onPostExecute(result); 

      // set instance fields in outer class...; 
      // set textView, progressBar, etc.. 

      if (result.MyCursor != null) 
      { 
       adapter.changeCursor(result.MyCursor); 
      } 

      connector.close(); // aren't i closing the db here??? 
         [Code to reload page with next detail items] 
     } 

    } 
} 
+0

你爲什麼不乾脆讓保存按鈕在onExExcute()中不可點擊並使其在onPostExecute()中再次可點擊 – 2012-01-04 12:22:51

+0

嗨midoalageb - 好問題,我的原始帖子顯然不夠清晰。該按鈕標題爲「保存並下一步」。數據保存後,視圖將重新加載列表中的下一條記錄。這就像是逐步瀏覽客戶和訂單列表。當頁面重新加載時,保存&下一步按鈕是可點擊的。 – Kevin 2012-01-04 22:28:00

+0

嘗試使用Synchronized語句來防止多個線程同時訪問相同的變量 – 2012-01-04 22:49:08

回答

0

如果(!result.MyCursor = NULL){ adapter.changeCursor(result.MyCursor); }

} 

}

connector.close(); }

試試這個。

+0

嗨Rashmi - 你是否建議我將'onPostExecute()'方法的**之外的connector.close()**? – Kevin 2012-01-02 06:16:36

+0

是的..如果這不起作用,那麼DB開放密切關係的最佳方法是使用try,catch和finally塊。你確定finally塊被執行,所以把connector.close()放在finally塊中。你的問題將得到解決 – 2012-01-02 06:24:40

+0

嗨,拉什米 - 這兩條建議都沒有奏效。我將嘗試從這篇文章http://www.touchlab.co/blog/single-sqlite-connection/中獲取一些來自@Kevin Galligan的內容,我將更新狀態。 – Kevin 2012-01-02 15:16:27

0

圍繞連接器做一個包裝,同步並作爲一個單例。我相信你正在同時訪問數據庫。這是我自己的一個的剝離版本:

(我重寫getWriteable數據庫,以使外鍵,但你不要有太多這樣做)

 public class DatabaseHelper extends SQLiteOpenHelper { 

    private static final String DATABASE_NAME = "myDatabase"; 
    private static final int DATABASE_VERSION = 1; 
    private Context context = null; 
    private static DatabaseHelper instance = null; 

    public static synchronized DatabaseHelper getInstance(Context context){ 

     if (instance == null){ 
      instance = new DatabaseHelper(context, null);   
     } 

     return instance; 
    } 

    @Override 
    public synchronized SQLiteDatabase getWritableDatabase() { 
     SQLiteDatabase db = super.getWritableDatabase(); 
     db.execSQL("PRAGMA foreign_keys=ON;"); 
     return db; 
    } 

    private DatabaseHelper(Context context, CursorFactory factory) { 
     super(context, DATABASE_NAME, factory, DATABASE_VERSION); 
     this.context = context; 
    } 


}