2013-06-25 4 views
0

Когда вы вызываете .close() в объект курсора, означает ли это, что для остальной части продолжительности действия он не может быть использован? Ниже приведен метод в моем объекте менеджер:Правильный способ обработки объектов курсора

Cursor cursor = null; 

try { 
    SQLiteDatabase db = openDb(); 
    cursor = db.query("table", null, "id=?", new String[] { id }, null, null, null); 

    cursor.moveToFirst(); 
    long dateTime = cursor.getLong(1); 

    cursor.close(); 
    return dateTime ; 
} catch (CursorIndexOutOfBoundsException e) { 
    return -1; 
} finally { 
    if (cursor != null) { 
     cursor.close(); 
    } 
    closeDb(); 
} 

Это метод, который бросает мне IllegalStateException. Однако есть небольшой поворот: он только выдает ошибку во второй раз, когда он вызывается. Трассировка StackTrace, я считаю, что линия вызывает у меня проблема заключается в следующем:

Cursor cursor = db.query("table", null, "id=?", new String[] { id }, null, null, null); 

Просто, чтобы очистить вещи немного, этот метод может быть вызван несколько раз в течение жизни своей деятельности путем щелканья конкретного элемента ListView. Методы openDb() и closeDb() следующим образом:

public SQLiteDatabase openDb() { 
    if (mDbHelper == null) { 
     mDbHelper = new DatabaseHelper(mContext); 
    } 
    return mDbHelper.getWritableDatabase(); 
} 

public void closeDb() { 
    mDbHelper.close(); 
} 

И они хранятся в суперкласс моего объекта Manager. mDbHelper - это статический объект.

Будучи совершенно новым для программирования на Android, мне интересно, почему это может вызвать у меня исключение. Единственное логическое объяснение, о котором я могу думать, это то, что объекты курсора фактически повторно используются, и они не должны закрываться на время действия. Я прав? И если я, когда вы на самом деле закрываете Курсор?

--- EDIT ---

После возился вокруг с кодом немного, я, кажется, получаю исключение бросают на гораздо более нерегулярной основе. По какой-то странной причине это происходит случайно; Я могу щелкнуть по восьми элементам списка ListView без проблем, и вдруг bam! Девятое приводит к сбою приложения.

Поскольку нажав на ListView также вызывает метод, который обновляет в тот же стол (который до сих пор не вызвала у меня никаких проблем до сих пор), я думаю, что это относится только, что я включаю, что хорошо:

try { 
    SQLiteDatabase db = openDb(); 

    ContentValues cv = new ContentValues(); 
    cv.put("id", id); 
    cv.put("dateTime", dateTime); 
    long affected = db.replace("table", null, cv); 

    return affected; 
} finally { 
    closeDb(); 
} 

Как вы можете видеть, здесь не задействована наука о ракетах. Тем не менее, этот метод сейчас начал бросать подобные исключения, происходит на линии:

long affected = db.replace("table", null, cv); 

я начинаю подозревать, что это щелчок слишком быстро проблема, и SQLite соединение не дает достаточно времени, чтобы Закрыть. Потому что нет никаких проблем с авариями, которые я могу различить; иногда он падает с третьей попытки, иногда на восьмой, иногда даже кажется, что он работает нормально до конца десятого.

Возможно ли это?

+0

Спасибо за ответы и комментарии ребята, но поскольку, похоже, не было ответа на случайность, я разработал обходное решение, чтобы поймать все Исключения и сделать что-то, когда они бывает. Я уверен, что там где-то есть ответ, который решит проблему полностью, а ум - только временный метод, поэтому я собираюсь оставить этот вопрос открытым для людей, чтобы ответить первым. – Wakka02

ответ

0

Поскольку вы вызываете метод close() для статического объекта, это может не обязательно «аннулировать» статический объект. Поэтому, когда вы проверяете, является ли mDbHelper нулевым в методе openDb() во второй раз, он пройдет это условие, и поэтому метод непреднамеренно вернет закрытую базу данных. Когда вы попытаетесь запросить эту закрытую базу данных, она, таким образом, выкинет недопустимое исключение.

Try:

public SQLiteDatabase closeDb() { 
    mDbHelper.close() 
    mDbHelper = null; 
} 

Я надеюсь, что я помог.

+0

Я так не думаю ... openDb() выполняет эту проверку, чтобы гарантировать, что NullPointers не будут выбрасываться, она все равно возвращает действительную открытую базу данных, используя .getWritableDatabase(). – Wakka02

+0

Можете ли вы проверить эту реализацию в своем кодировании? – frogmanx

+0

Я только что сделал, это не решило проблему ... вот как я придумал теорию в своем комментарии. – Wakka02

1

Как говорят docs после того, как вы вызвали close(), ваш курсор будет навсегда недействительным.

Кроме того, нет необходимости называть close 2 раза в вашей функции. Достаточно называть его только в блоке finally

+0

Я создаю новый курсор, используя db.query() каждый раз, хотя. Так что это не должно быть проблемой? – Wakka02

+0

@ Wakka02 в этом нет проблем, если вы не забыли закрыть его после его использования. – 7bluephoenix

+0

Я действительно закрываю его. Я включил cursor.close() во все мои окончательные утверждения. Спасибо Алексу за то, что он указал здесь на double .close(), я уже исправил это. Тем не менее, нет. : / – Wakka02