Отчеты по журналу sqlite для Android и db.close () - PullRequest
2 голосов
/ 11 января 2011

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

private Handler handler = new Handler() {
    public void handleMessage(Message msg) {
        switch(msg.what) {
        case 1:
            dh.open();
            dh.updateEvent("id", "name", "someone");
            dh.close();
            successAlert.show();
            break;
        case 2:
            failAlert.show();
            break;
        }
    }
};

Раньше у меня не было "dh.close ()", и это когда журнал сообщал, что база данных / курсор не закрыты.Но с тех пор, как я добавил это, это занимает очень много времени.Когда я получаю сообщение, система зависает.Я делаю что-то не так или обычно это занимает много времени.Я также пытался использовать блок try с finally для закрытия БД.

РЕДАКТИРОВАТЬ:

public class DatabaseHelper {

private Database dbHelper;
private SQLiteDatabase db;
private Context context;

public DatabaseHelper(Context context) {
    this.context = context;
    //database = new Database(context);
}

public void open() {
    dbHelper = new Database(context);
    db = dbHelper.getWritableDatabase();
}

public void close() {
    dbHelper.close();
}

public void updateEvent(int id, String name, int other) {
    ContentValues cv = new ContentValues();
    cv.put("id", id);
    cv.put("name", name);
    cv.put("other", other);
    db.update("stateTable", cv, "id=" + id, null);
}

public boolean checkState(int id) {
    db = dbHelper.getReadableDatabase();
    Cursor cursor = db.query("stateTable", null, null, null, null, null, null);
    cursor.moveToPosition(id - 1);
    int i = cursor.getInt(2);
    android.util.Log.d("semajhan", ": " + i);
    if (i == 1) {
        return true;
    } else {
        return false;
    }
}

}

Extended SQLiteOpenHelper:

public class Database extends SQLiteOpenHelper {

private static final String DATABASE_NAME = "events.db";
private static final int DATABASE_VERSION = 1;
private static final String TABLE_NAME = "stateTable";
private static final String ID = "id";
private static final String NAME = "name";
private static final String OTHER = "other";
private static final String DATABASE_CREATE = "CREATE TABLE stateTable (id INT, name TEXT, other INT)";
private static final String DATABASE_UPGRADE = "DROP TABLE IF EXISTS table";

public Database(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
    // TODO Auto-generated constructor stub
}

@Override
public void onCreate(SQLiteDatabase db) {
    // TODO Auto-generated method stub
    db.execSQL(DATABASE_CREATE);
    // added initial values
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // TODO Auto-generated method stub
    db.execSQL(DATABASE_UPGRADE);
    onCreate(db);
}

}

01-11 13:57:41.239: ERROR/ActivityManager(61): ANR in com.semajhan.soodles  (com.semajhan.soodles/.Level1)
01-11 13:57:41.239: ERROR/ActivityManager(61): Reason: keyDispatchingTimedOut
01-11 13:57:41.239: ERROR/ActivityManager(61): Load: 1.64 / 0.56 / 0.26
01-11 13:57:41.239: ERROR/ActivityManager(61): CPU usage from 35716ms to -1ms ago:
01-11 13:57:41.239: ERROR/ActivityManager(61):   44% 862/com.semajhan.soodles: 37% user + 7.2% kernel / faults: 853 minor
01-11 13:57:41.239: ERROR/ActivityManager(61):   29% 61/system_server: 27% user + 1.9% kernel / faults: 142 minor
01-11 13:57:41.239: ERROR/ActivityManager(61):   0.2% 731/com.android.quicksearchbox: 0% user + 0.2% kernel / faults: 30 minor
01-11 13:57:41.239: ERROR/ActivityManager(61):   0.2% 707/com.android.launcher: 0.2% user + 0% kernel / faults: 30 minor
01-11 13:57:41.239: ERROR/ActivityManager(61):   0.2% 801/com.svox.pico: 0.1% user + 0.1% kernel / faults: 363 minor
01-11 13:57:41.239: ERROR/ActivityManager(61):   0% 117/com.android.systemui: 0% user + 0% kernel
01-11 13:57:41.239: ERROR/ActivityManager(61):   0% 41/adbd: 0% user + 0% kernel
01-11 13:57:41.239: ERROR/ActivityManager(61): 99% TOTAL: 86% user + 13% kernel + 0% irq
01-11 13:57:41.239: ERROR/ActivityManager(61): CPU usage from 1969ms to 2620ms later:
01-11 13:57:41.239: ERROR/ActivityManager(61):   54% 61/system_server: 48% user + 6% kernel
01-11 13:57:41.239: ERROR/ActivityManager(61):     40% 69/SurfaceFlinger: 40% user + 0% kernel
01-11 13:57:41.239: ERROR/ActivityManager(61):     10% 92/InputDispatcher: 7.5% user + 3% kernel
01-11 13:57:41.239: ERROR/ActivityManager(61):     1.5% 62/HeapWorker: 1.5% user + 0% kernel
01-11 13:57:41.239: ERROR/ActivityManager(61):   44% 862/com.semajhan.soodles: 32% user + 12% kernel / faults: 2 minor
01-11 13:57:41.239: ERROR/ActivityManager(61):     24% 874/Thread-13: 24% user + 0% kernel
01-11 13:57:41.239: ERROR/ActivityManager(61):     23% 862/studios.soodles: 4.6% user + 18% kernel
01-11 13:57:41.239: ERROR/ActivityManager(61):     1.5% 867/Compiler: 0% user + 1.5% kernel
01-11 13:57:41.239: ERROR/ActivityManager(61):   0.8% 731/com.android.quicksearchbox: 0% user + 0.8% kernel
01-11 13:57:41.239: ERROR/ActivityManager(61):     0.8% 732/HeapWorker: 0% user + 0.8% kernel
01-11 13:57:41.239: ERROR/ActivityManager(61): 100% TOTAL: 76% user + 23% kernel

Ответы [ 3 ]

5 голосов
/ 11 января 2011

Первый вызов getReadableDatabase или getWritableDatabase экземпляра SQLiteOpenHelper занимает действительно длительное время для завершения. Вам не следует создавать новый объект Database (ваш экземпляр SQLiteOpenHelper) каждый раз, когда вам нужно выполнить запрос к базе данных. Попробуйте использовать тот же экземпляр Database в DatabaseHelper.

При использовании SQLiteOpenHelper вы не хотите закрывать объект SQLiteDatabase для SQLiteOpenHelper, потому что он является общим; т.е. getWritableDatabase всегда возвращает один и тот же SQLiteDatabase объект.

Обратите внимание, что ваш метод checkState пропускает курсор. Чтобы предотвратить утечку курсора, я всегда использую try - finally после получения курсора. Например:

    db = dbHelper.getReadableDatabase();
    Cursor cursor = db.query("stateTable", null, null, null, null, null, null);
    try {
        cursor.moveToPosition(id - 1);
        int i = cursor.getInt(2);
        android.util.Log.d("semajhan", ": " + i);
        if (i == 1) {
                return true;
        } else {
                return false;
        }
    } finally {
        cursor.close();
    }
3 голосов
/ 11 января 2011

Интересно, такая же проблема, как в этот ответ : основная проблема в том, что действия должны иметь метод onDestroy, который закрывает DatabaseHelper. (Все, что я могу сейчас сказать, это то, что вы не покажите onDestroy метод, но это, очевидно, лишь часть вашего кода.) Я также написал в блоге об этой проблеме здесь .

Вы также написали, что «Но с тех пор, как я добавил [dh.close()], это займет очень много времени». Вы делаете много записей в базу данных? Возможно, вам нужно использовать транзакции для периодической очистки этих записей. Если вы читаете только из базы данных, то я понятия не имею, почему вызов close займет много времени. Но, не видя больше вашего кода, это только догадки.

РЕДАКТИРОВАТЬ: ccheneson Совет по поводу вызова db.close() до вызова dbHelper.getReadableDatabase() стоит следовать. Тем не менее, вы должны проверить, что db не является нулевым. Это изменит checkState на:

public boolean checkState(int id) {
    if (db != null) {
        db.close();
    }
    db = dbHelper.getReadableDatabase();
    // ... etc ....

Если это окажется реальной проблемой, пожалуйста, примите ответ ccheneson, а не мой.

(Выше редактирование было неправильным; я должен был знать лучше! См. Ниже.)

РЕДАКТИРОВАТЬ 1 : Я не уверен, почему вы вообще заново открываете базу данных этим методом. Предполагая, что ваш метод DatabaseHelper.open вызван, у вас есть читаемый дескриптор базы данных и . checkState не нужно повторно открывать его для чтения.

EDIT 2 : Однако SQLiteOpenHelper.getReadableDatabase почти всегда будет возвращать тот же дескриптор базы данных, который был возвращен из SQLiteOpenHelper.getWriteableDatabase. Вам не нужно явно закрывать дескриптор базы данных; SQLiteOpenHelper закроет его для вас. Вы do должны быть уверены, что SQLiteOpenHelper.close вызывается, когда ваша деятельность разрушается (как я писал выше.)

1 голос
/ 11 января 2011
public void close() {
    dbHelper.close(); // to change to db.close(); ?
}

Я думаю, что здесь вы хотели бы закрыть дескриптор базы данных db вместо dbHelper

Также у вас checkState метод:

public boolean checkState(int id) {
    db = dbHelper.getReadableDatabase();
    Cursor cursor = db.query("stateTable", null, null, null, null, null, null);
    cursor.moveToPosition(id - 1);
    int i = cursor.getInt(2);
    android.util.Log.d("semajhan", ": " + i);
    if (i == 1) {
        return true;
    } else {
        return false;
    }
}

Выхотел бы закрыть курсор как:

int i = cursor.getInt(2);
cursor.close();
android.util.Log.d("semajhan", ": " + i);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...