2012-01-02 101 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; 
    } 


}