Java: ORMLite с SimpleCursorAdapter: StaleDataException

Я впервые тестирую SimpleCursorAdapter. Я хочу использовать его с ORMLite.

К сожалению, всегда получаю StaleDataException :(

РЕДАКТИРОВАТЬ: больше не уверен, является ли проблема с адаптером.swapCursor (c). перешагнул через это без проблем. проблема, кажется, где-то еще / КОНЕЦ РЕДАКТИРОВАНИЯ

Похоже, что ошибка возникает в файле adapter.swapCursor (c). c закрыт, похоже, это проблема, как я могу это исправить и почему именно он закрыт? Примечание: ошибка возникает ТОЛЬКО, если таблица sqllite Einsatz1 содержит данные. Все работает отлично, если таблица пуста.

Это моя деятельность:

public class UebersichtEinsaetze extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor>
{
...

  public DatabaseHelper helper = null;

  @Override
  protected void onDestroy()
  {
    super.onDestroy();
    ((SimpleCursorAdapter) einsatzListView.getAdapter()).getCursor().close();
    helper.close();
    if (helper != null)
    {
      OpenHelperManager.releaseHelper();
      helper = null;
    }

  }

  private DatabaseHelper getHelper()
  {
    if (helper == null)
    {
      helper = OpenHelperManager.getHelper(this, DatabaseHelper.class);
    }
    return helper;
  }

  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_ubersicht_einsaetze);
    einsatzListView = (ListView) findViewById(android.R.id.list);
    einsatzDatumTextView = (TextView) findViewById(R.id.tv_uebersicht_abdatum);
    fillData();
    getHelper();
  }

  private void fillData()
  {
    String[] from = new String[] { "_id" };
    int[] to = new int[] { R.id.view_list_einsatz_text_projnr };

    adapter = new SimpleCursorAdapter(this, R.layout.view_list_eintrag_einsatz, null, from, to, 0);
    getSupportLoaderManager().initLoader(0, null, this);
    einsatzListView.setAdapter(adapter);
  }

  @Override
  public Loader<Cursor> onCreateLoader(int id, Bundle args)
  {
    String[] projection = { "_id" };
    CursorLoader cursorLoader = new CursorLoader(this, test.CONTENT_URI, projection, null, null, null);
    return cursorLoader;
  }

  @Override
  public void onLoadFinished(Loader<Cursor> loader, Cursor c)
  {
    adapter.swapCursor(c);
  }

  @Override
  public void onLoaderReset(Loader<Cursor> loader)
  {
    adapter.swapCursor(null);
  }
}

Это мой Contentprovider:

 private DatabaseHelper database;
  private RuntimeExceptionDao<Einsatz1, String> dao;

  // Used for the UriMacher
  private static final int EINSAETZE = 10;
  private static final int EINSATZ_ID = 20;

  private static final String AUTHORITY = "de.myapp.android";

  private static String BASE_PATH = "einsaetze";
  public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);

  public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/einsaetze";
  public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/einsatz";

  private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
  static
  {
    sURIMatcher.addURI(AUTHORITY, BASE_PATH, EINSAETZE);
    sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/#", EINSATZ_ID);
  }

@Override
  public boolean onCreate()
  {
    database = new DatabaseHelper(getContext());
    this.dao = (RuntimeExceptionDao<Einsatz1, String>) database.getRTE(Einsatz1.class);
    return false;
  }

@Override
  public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
  {
    // ignore method parameters for now just to get it basically working

    QueryBuilder<Einsatz1, String> queryBuilder = this.dao.queryBuilder();

    Cursor cursor = null;
    CloseableIterator<Einsatz1> iterator = null;
    try
    {
      iterator = dao.iterator(queryBuilder.prepare());
      AndroidDatabaseResults results = (AndroidDatabaseResults) iterator.getRawResults();
      cursor = results.getRawCursor();
    }
    catch (SQLException e)
    {
      Log.e(getClass().getName(), "get cursor", e);
    }
    finally
    {
      iterator.closeQuietly();
    }

    // Make sure that potential listeners are getting notified
    cursor.setNotificationUri(getContext().getContentResolver(), uri);

    return cursor;
  }

Logcat:

01-09 10:01:29.591: E/AndroidRuntime(3767): FATAL EXCEPTION: main
01-09 10:01:29.591: E/AndroidRuntime(3767): android.database.StaleDataException: Attempting to access a closed CursorWindow.Most probable cause: cursor is deactivated prior to calling this method.
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:139)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.database.CursorWrapper.getString(CursorWrapper.java:114)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.support.v4.widget.SimpleCursorAdapter.bindView(SimpleCursorAdapter.java:135)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.support.v4.widget.CursorAdapter.getView(CursorAdapter.java:256)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.widget.AbsListView.obtainView(AbsListView.java:2267)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.widget.ListView.measureHeightOfChildren(ListView.java:1244)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.widget.ListView.onMeasure(ListView.java:1156)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.View.measure(View.java:15172)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.widget.RelativeLayout.measureChild(RelativeLayout.java:602)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:415)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.View.measure(View.java:15172)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.View.measure(View.java:15172)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.widget.LinearLayout.measureVertical(LinearLayout.java:833)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.View.measure(View.java:15172)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2148)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.View.measure(View.java:15172)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1848)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1100)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1273)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:998)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4212)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.Choreographer.doCallbacks(Choreographer.java:555)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.Choreographer.doFrame(Choreographer.java:525)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.os.Handler.handleCallback(Handler.java:615)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.os.Handler.dispatchMessage(Handler.java:92)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.os.Looper.loop(Looper.java:137)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at android.app.ActivityThread.main(ActivityThread.java:4745)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at java.lang.reflect.Method.invokeNative(Native Method)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at java.lang.reflect.Method.invoke(Method.java:511)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
01-09 10:01:29.591: E/AndroidRuntime(3767):     at dalvik.system.NativeStart.main(Native Method)

Небольшое примечание (неважно, но если у кого-то есть информация ...): когда я устанавливаю точку останова перед адаптером.swapCursor (c), он не останавливается на достигнутом, прежде чем выдает ошибку. Мне нужно установить точку останова, чтобы перед этим оператором вставить фиктивный int bla = 123. Точно так же установка точки останова в любом месте в общедоступном методе запроса Cursor (...) заставляет все выполняться без ошибок (какого черта ...), но снова не останавливается на точке останова.


person cdbeelala89    schedule 09.01.2013    source источник
comment
'UebersichtEinsaetze'? Что это значит? : -)   -  person Piotr    schedule 08.07.2014


Ответы (2)


РЕШЕНО

Закомментируйте

iterator.closeQuietly();

Хотя я нашел код, он пришел отсюда:

Курсор Android с ORMLite для использования в CursorAdapter

... не стоит полагаться на это.

Мне нужно будет посмотреть, какие потенциальные негативные последствия будет иметь комментирование (если кто-то знает, скажите мне), но сейчас все, похоже, работает.

person cdbeelala89    schedule 09.01.2013

да, похоже, что это из-за iterator.closeQuietly (), хотя эффект комментирования этого заключается в том, что теперь у вас может быть утечка со многими открытыми итераторами (которые действительно должны быть закрыты).

Вместо этого в вашем методе onQuery () попробуйте использовать следующее, которое даст вам ссылку на Cursor, который должен закрываться, когда ваш ContentProvider закрыт.

Cursor cursor = getHelper().getReadableDatabase().query(tableName, projection, selection, selectionArgs, groupBy, having, sortOrder)
person jklp    schedule 22.06.2013