StaleDataException с диалоговым окном
Я пытаюсь показать диалог со списком с именами из моей базы данных, но я продолжаю получать 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()
линия работает нормально, но я не могу просто оставить курсор открытым, хотя что мне делать?
3 ответа
Вы не можете закрыть курсор, пока CursorAdapter больше не нужен. Так что вы можете закрыть его в методе onDestroy():
@Override
public void onDestroy() {
super.onDestroy();
ListView lv = (ListView) d.findViewById(R.id.dialog_list);
((CursorAdapter) lv.getAdapter()).getCursor().close();
database.close();
}
Вы получаете свою ошибку, потому что вы закрываете Cursor
в то время как SimpleCursorAdapter
Возможно, вы все еще пытаетесь получить доступ к данным из него.
Если вы хотите использовать CursorLoader
, как вы должны делать.
- Сохраните ссылку на ваш адаптер в качестве переменной экземпляра.
- Создайте свой простой адаптер курсора со ссылкой на ноль для курсора
- Пусть ваш класс реализует
LoaderManager.LoaderCallbacks<Cursor>
- На самом деле создать
CursorLoader
вonCreateLoader
- В
onLoadFinished()
поменяйте местами курсорыadapter.swapCursor(cursor)
- В
onLoaderReset()
, поменяйте местами курсор сnull
курсор как adapter.swapCursor(null)`
Вы также должны в конечном итоге поместить свои данные в ContentProvider - это не так уж плохо!
Я привык полагаться на startManagingCursor
способ избавиться от хлопот открытия и закрытия Cursors
в систему. Теперь, когда он устарел (он все еще работает, но я бы не рекомендовал его использовать), рассмотрите возможность использования CursorLoader
класс с LoaderManager
и оставьте это системе для обработки закрытия курсора.