Базы данных Android SQLite закрываются в запросе () - PullRequest
0 голосов
/ 03 февраля 2012

Я вижу, что ContentProvider.query () возвращает объект Cursor.Обычно курсор является результатом запроса SQLiteDatabase.В следующем фрагменте кода:

public Cursor query() {     
        try {
            SQLiteDatabase db = this.getReadableDatabase(); 
            Cursor c = db.query(Cfg.table_name, new String[] {"*"}, null, null, null, null, null);
            return c;
        }
        catch(Exception exp) {
        }

        return null;
    }

В коде дБ не закрыта.Есть ли проблема?

Ответы [ 2 ]

2 голосов
/ 03 февраля 2012

Да, я считаю, что есть проблема.Вы можете передать 'db' в качестве аргумента, тогда вызывающий может закрыть его, когда закончите с курсором.

1 голос
/ 03 февраля 2012

Вы пытаетесь закрыть БД, когда закончите?Если это так, попробуйте:

public Cursor query() {
        SQLiteDatabase db = null;   
        try {
            SQLiteDatabase db = this.getReadableDatabase(); 
            Cursor c = db.query(Cfg.table_name, new String[] {"*"}, null, null, null, null, null);
            return c;
        }
        catch(Exception exp) {
        }finally{
           try{if(null != db){ db.close(); db = null;}}catch(Exception e){}
        }

        return null;
    }

Это должно правильно закрывать БД каждый раз.Если вам интересно, почему оно не закрыто, я бы изучил, что говорит это перехваченное Exception.

Кстати, я бы заменил "new String [] {" * "}" на ноль.http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html

ОБНОВЛЕНИЕ: Хорошо, теперь я понимаю проблему.Возможно, вам придется немного перестроить свой класс.

TLDR: Идеально для меня то, что вы должны закончить, это два класса.Один из них - помочь вам открыть БД.Второй будет содержать объект SQLiteDatabase в качестве свойства.Вы можете открыть соединение и инициализировать объект DB, как только создадите этот класс (или создадите метод, используемый для открытия базы данных).Все методы будут использовать объект db только для SCUD.Тогда все закрытие или декомпозицию объекта БД можно поместить в метод или переопределить onDestroy.Пример ниже, но если у вас есть время, чтобы сэкономить, это хороший учебник http://www.vogella.de/articles/AndroidSQLite/article.html.

Первый - DBOpenHelper.Целью этого класса будет управление таблицами и помощь в открытии базы данных для модификации.

package com.mondial.th.rsa.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

/**
 * DBOpenHelper helps opening database and managing database's upgrade or creation.
 * @author Poohdish Rattanavijai
 *
 */
public class DBOpenHelper extends SQLiteOpenHelper {
    private static final String TAG = DBOpenHelper.class.getSimpleName();
    private static final int DATABASE_VERSION = 2;
    private static final String DATABASE_NAME = "rsa_db";

    public DBOpenHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    public DBOpenHelper(Context context, String name, CursorFactory factory,
            int version) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase database) {
        Log.d(TAG, "DBOpenHelper.onCreate");
        // Create table goes here.
    }

    @Override
    public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
        // Drop and recreate table goes here.
    }

}

Второй класс будет обрабатывать все запросы для вас, используя DBOpenHelper, показанный ранее.

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.mondial.th.rsa.vo.ProfileVO;

/**
 * Database adapter for managing Profile table
 * @author Poohdish Rattanavijai
 *
 */
public class ProfileDBAdapter {
    private static final String TAG = ProfileDBAdapter.class.getName();
    private Context context;
    private SQLiteDatabase db;
    private DBOpenHelper dbHelper;

    public ProfileDBAdapter(Context context){
        this.context = context;
    }

    /**
     * Open writable database.
     * @return writable SQLDatabase
     * @throws SQLException
     */
    public ProfileDBAdapter open() throws SQLException{
        Log.d(TAG, "Open ProfileDBAdapter");
        dbHelper = new DBOpenHelper(context);

        db = dbHelper.getWritableDatabase();
        return this;
    }

    /**
     * Close database; Exception omitted
     */
    public void close(){
        try {
            dbHelper.close();
        } catch (Exception e) {
            //e.printStackTrace();
        }
    }

    /**
     * Creating new record in profile table with given VO.
     * @param profile VO representing data in the new record.
     * @return the row ID of the newly inserted row, or -1 if an error occurred.
     */
    public long createProfile(ProfileVO profile){
        ContentValues values = createContentValues(profile);
        return db.insert(ProfileVO.TABLE_NAME, null, values);
    }

    /**
     * Updating record in profile table with given VO by using ID column.
     * @param profile VO representing new data to updated.
     * @return the number of rows affected .
     */
    public boolean updateProfile(ProfileVO profile){
        ContentValues values = createContentValues(profile);
        return db.update(ProfileVO.TABLE_NAME, values, ProfileVO.COLUMN_ID + "=" + profile.getId(), null) > 0;
    }

    /**
     * Deleting a row representing given VO off profile table by using ID column.
     * @param profile
     * @return
     */
    public boolean deleteProfile(ProfileVO profile){
        return deleteProfile(profile.getId());
    }

    /**
     * Deleting a row off profile table with given ID column.
     * @param profile
     * @return
     */
    public boolean deleteProfile(long rowId){
        return db.delete(ProfileVO.TABLE_NAME, ProfileVO.COLUMN_ID + "=" + rowId, null) > 0;
    }

    /**
     * open cursor representing every records in profile table.
     * @return Cursor representing every records in profile table.
     */
    public Cursor fetchAllProfiles(){
        return db.query(ProfileVO.TABLE_NAME, null, null, null, null, null, null);
    }

    /**
     * open cursor representing a row in profile table with given ID.
     * @return Cursor representing a row in profile table with given ID.
     */
    public Cursor fetchProfile(long rowId){
        Cursor mCursor = db.query(true, ProfileVO.TABLE_NAME, null, ProfileVO.COLUMN_ID + "=" + rowId
                , null, null, null, null, null);

        if(null != mCursor){
            mCursor.moveToFirst();
        }

        return mCursor;
    }

    /**
     * This class translate given VO into ContentValues for ContentResolver to parse data and talk to the database.
     * @param profile VO
     * @return ContentsValues containing given VO's data except ID.
     */
    private ContentValues createContentValues(ProfileVO profile){
        ContentValues values = new ContentValues();

        values.put(ProfileVO.COLUMN_DOB, profile.getDob());
        values.put(ProfileVO.COLUMN_FIRSTNAME, profile.getFirstname());
        values.put(ProfileVO.COLUMN_LASTNAME, profile.getLastname());

        return values;
    }
}

Тогда у вас есть один идеальный класс, который действует как DAO.Для приведенного выше примера использование будет.

ProfileDBAdapter dbHelper = new ProfileDBAdapter(context);
dbHelper.open();
cursor = dbHelper.fetchAllProfiles();
if(cursor.getCount() > 0){
 //TODO Data exists, do stuff.
}
try {
    if(null != cursor && !cursor.isClosed()){
       cursor.close();
    }
} catch (Exception e) {
    e.printStackTrace();
}

if(null != dbHelper){
    dbHelper.close();
    dbHelper = null;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...