Закрытие курсора в функции, которая возвращает курсор - PullRequest
0 голосов
/ 23 мая 2018

У меня проблема с закрытием курсора в моем классе SQLite.Когда я закрою Курсор и SQLiteDatabase в блоке finally (в DBHelper), я не могу прочитать данные в моем другом классе (Невозможно повторно открыть ошибку закрытого Курсора), но когда я не закрываю Курсор и SQLiteDatabase тогда у меня есть ошибки утечки памяти.

DHHelper.java:

//...
public Cursor selectData(String selectVal, String tabName){
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor c = null;
    try {
        String areaTyp = "SELECT " + selectVal + "  FROM " + tabName;
        c = db.rawQuery(areaTyp, null);
        return c;
    } finally {
        c.close();
        db.close();
    }
}
//...

UserMenager.java

    public List<UserModel> getUsersList(){
    List<UserModel> allUsers = new ArrayList<UserModel>();

    final DBHelper db = new DBHelper(appStatic.CONTEX);
    Cursor c = db.selectData("*","User");
    if (c.moveToFirst()) {
        while (!c.isAfterLast()) {

            allUsers.add(new UserModel(c.getString(c.getColumnIndex("cms_id")),
                    c.getString(c.getColumnIndex("login")),
                            c.getString(c.getColumnIndex("name")),
                                    c.getString(c.getColumnIndex("active")),
                                            c.getString(c.getColumnIndex("avatar")),
                                                    c.getString(c.getColumnIndex("gtoken"))));

            c.moveToNext();
        }
    }
    c.close();
    db.close();

    return allUsers;
}

Может быть, я должен сделать это по-другому, и функциячто возвращает курсор это плохая идея?

РЕДАКТИРОВАНИЕ: Когда я запускаю приложение, у меня появляется ошибка:

java.lang.IllegalStateException: попытка повторно открыть уже закрытый объект: SQLiteQuery: SELECT * FROM User

В UserMenager.java, строка

if (c.moveToFirst()) {

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

Я бы предложил вернуть в качестве конечного результата то, что вы хотите, то есть ArrayList, из класса selectData.Затем вы можете закрыть Курсор и Базу данных в методе selectData, как только они будут выполнены.

, например: -

public ArrayList<UserModel> selectData(String selectVal, String tabName){
    SQLiteDatabase db = this.getWritableDatabase(); //<<<< getReadable will most likely return a writeable database anyway
    ArrayList<UserModel> rv = new ArrayList<>();
    Cursor c = db.query(
            tabName,
            new String[]{selectVal},
            null,
            null,
            null,
            null,
            null
    );
    while (c.moveToNext()) {
        rv.add(new UserModel(
                c.getString(c.getColumnIndex("cms_id")),
                c.getString(c.getColumnIndex("login")),
                c.getString(c.getColumnIndex("name")),
                c.getString(c.getColumnIndex("active")),
                c.getString(c.getColumnIndex("avatar")),
                c.getString(c.getColumnIndex("gtoken"))
        ));
    }
    c.close();
    db.close();
    return rv;
}

Наряду с: -

public List<UserModel> getUsersList(){
    List<UserModel> allUsers = new ArrayList<UserModel>();

    final DBHelper db = new DBHelper(appStatic.CONTEX);
    return selectData("*","Users");
}
  • Обтекание try / catch вокруг методов SQLiteDatabase имеет тенденцию вызывать больше разочарования и путаницы, чем могло бы быть вызвано.
  • Обычно удобные методы рекомендуются по сравнению с использованием rawQuery и execSQL методы (в данном случае query - это удобный метод).
  • В идеале selectVal должен быть строкой [] столбцов, а не просто строкой, чтобы соответствоватьquery удобный метод.
  • Как прокомментировано getReadableDatabase редко получает базу данных только для чтения согласно
  • Создание и / или открытие базы данных.Это будет тот же объект, возвращаемый функцией getWritableDatabase (), если для какой-либо проблемы, например, для полного диска, база данных должна быть открыта только для чтения.В этом случае будет доступен объект базы данных только для чтения.Если проблема устранена, будущий вызов getWritableDatabase () может завершиться успешно, и в этом случае объект базы данных только для чтения будет закрыт, а объект чтения / записи будет возвращен в будущем. SQLiteDatabase getReadableDatabase
0 голосов
/ 23 мая 2018

Код после return недоступен - никогда не будет выполнен.

...