7

我正在尝试显示一个带有列表视图的对话框,其中包含我数据库中的名称,但我不断得到一个StaleDataException. 我知道这通常意味着我正在尝试使用来自已关闭游标的数据,但在我获得所有数据之前,游标不会关闭,所以我不明白为什么我会得到这个

d = new Dialog(this);
d.setContentView(R.layout.dialog_layout);
d.setTitle("Select Bowler");

ListView lv = (ListView)d.findViewById(R.id.dialog_list);
Cursor c = getContentResolver().query(
    BowlersDB.CONTENT_URI,
    new String[] {
        BowlersDB.ID, BowlersDB.FIRST_NAME, BowlersDB.LAST_NAME
    },
    null,
    null,
    BowlersDB.LAST_NAME + " COLLATE LOCALIZED ASC"
);

if (c.moveToFirst() && c != null) {
    SimpleCursorAdapter adapter = new SimpleCursorAdapter(
        this,
        R.layout.names_listview,
        c,
        new String[] {
            BowlersDB.FIRST_NAME, BowlersDB.LAST_NAME
        },
        new int[] {
            R.id.bListTextView, R.id.bListTextView2
        },
        0
    );
    lv.setAdapter(adapter);
    lv.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> arg0, View v, int position, long id) {
            bowlerClickedID = id;
            updateName(id);
        }
    });
    d.show();
}
c.close();

错误

android.database.StaleDataException: 
   Attempting to access a closed CursorWindow. 
   Most probable cause: cursor is deactivated prior to calling this method.

   at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:139)
   at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
   at android.database.CursorWrapper.getString(CursorWrapper.java:114)
   at android.widget.SimpleCursorAdapter.bindView(SimpleCursorAdapter.java:150)
   at android.widget.CursorAdapter.getView(CursorAdapter.java:250)
   at android.widget.AbsListView.obtainView(AbsListView.java:2267)
   at android.widget.ListView.measureHeightOfChildren(ListView.java:1244)
   at android.widget.ListView.onMeasure(ListView.java:1156)
   at android.view.View.measure(View.java:15172)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
   at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1390)
   at android.widget.LinearLayout.measureVertical(LinearLayout.java:681)
   at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
   at android.view.View.measure(View.java:15172)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
   at android.view.View.measure(View.java:15172)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
   at android.view.View.measure(View.java:15172)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
   at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1390)
   at android.widget.LinearLayout.measureVertical(LinearLayout.java:681)
   at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
   at android.view.View.measure(View.java:15172)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
   at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2148)
   at android.view.View.measure(View.java:15172)
   ...

编辑:如果我注释掉该c.close()行,它工作正常,但我不能只是让光标保持打开状态,我该怎么办?

4

3 回答 3

9

您收到错误是因为您正在关闭CursorSimpleCursorAdapter创建的可能仍在尝试从中访问数据的时间。

如果你想使用 a CursorLoader,你应该这样做。

  1. 保留对适配器的引用作为实例变量
  2. 使用对光标的 null 引用创建简单的光标适配器
  3. 让你的班级实施LoaderManager.LoaderCallbacks<Cursor>
  4. 实际上创建CursorLoaderonCreateLoader
  5. onLoadFinished()中,将光标与adapter.swapCursor(cursor)
  6. onLoaderReset()中,将光标与null光标交换为 adapter.swapCursor(null)`

您还应该最终将数据放入 ContentProvider - 这还不错!

于 2012-10-09T09:34:00.387 回答
4

在不再需要 CursorAdapter 之前,您无法关闭光标。所以你可以在 onDestroy() 方法中关闭它:

@Override
public void onDestroy() {
 super.onDestroy();

 ListView lv = (ListView) d.findViewById(R.id.dialog_list);
 ((CursorAdapter) lv.getAdapter()).getCursor().close();
 database.close();
}
于 2012-10-02T16:44:55.723 回答
0

以前是靠startManagingCursor方法把开闭的麻烦留给Cursors系统。现在它已被弃用(它仍然有效,但我不建议使用它),考虑使用CursorLoader该类LoaderManager并将其留给系统来处理光标关闭。

于 2012-10-03T08:46:14.137 回答