Android 尝试重新打开一个已经关闭的对象 sqlitedatabase

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23166323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 06:51:21  来源:igfitidea点击:

Attempt to reopen an already-closed object sqlitedatabase

androidsqliteandroid-sqlite

提问by Namikaze Minato

I have a databaseHandler. I need to count the rows in table. App crashes by this error: android attempt to reopen an already-closed object sqlitedatabase.
I simply use this code in activity:

我有一个databaseHandler。我需要计算表中的行数。应用程序因以下错误而崩溃:android attempt to reopen an already-closed object sqlitedatabase
我只是在活动中使用此代码:

db.getContactsCount();

But app crashes. Furthemore I want to reset the tables (delete table rows). I added the method below:

但应用程序崩溃。此外,我想重置表格(删除表格行)。我添加了以下方法:

public void deleteTable() {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete("contacts", null, null);
    }

It works good but I can't use this one:

它工作得很好,但我不能使用这个:

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // Drop older table if existed
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_CONTACTS);

    // Create tables again
    onCreate(db);
}

This is the databasehandler:

这是数据库处理程序:

public class DatabaseHandler extends SQLiteOpenHelper {

// All Static variables
// Database Version
private static final int DATABASE_VERSION = 1;

// Database Name
private static final String DATABASE_NAME = "contactsManager";

// Contacts table name
private static final String TABLE_CONTACTS = "contacts";

// Contacts Table Columns names
private static final String KEY_ID = "id";
private static final String KEY_NAME = "name";
private static final String KEY_PH_NO = "phone_number";

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

// Creating Tables
@Override
public void onCreate(SQLiteDatabase db) {
    String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_CONTACTS + "("
            + KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT,"
            + KEY_PH_NO + " TEXT" + ")";
    db.execSQL(CREATE_CONTACTS_TABLE);
}

// Upgrading database
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // Drop older table if existed
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_CONTACTS);

    // Create tables again
    onCreate(db);
}

/**
 * All CRUD(Create, Read, Update, Delete) Operations
 */

// Adding new contact
void addContact(Contact contact) {
    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put(KEY_NAME, contact.getName()); // Contact Name
    values.put(KEY_PH_NO, contact.getPhoneNumber()); // Contact Phone

    // Inserting Row
    db.insert(TABLE_CONTACTS, null, values);
    db.close(); // Closing database connection
}

// Getting single contact
Contact getContact(int id) {
    SQLiteDatabase db = this.getReadableDatabase();

    Cursor cursor = db.query(TABLE_CONTACTS, new String[] { KEY_ID,
            KEY_NAME, KEY_PH_NO }, KEY_ID + "=?",
            new String[] { String.valueOf(id) }, null, null, null, null);
    if (cursor != null)
        cursor.moveToFirst();

    Contact contact = new Contact(Integer.parseInt(cursor.getString(0)),
            cursor.getString(1), cursor.getString(2));
    // return contact
    return contact;
}

// Getting All Contacts
public List<Contact> getAllContacts() {
    List<Contact> contactList = new ArrayList<Contact>();
    // Select All Query
    String selectQuery = "SELECT  * FROM " + TABLE_CONTACTS;

    SQLiteDatabase db = this.getWritableDatabase();
    Cursor cursor = db.rawQuery(selectQuery, null);

    // looping through all rows and adding to list
    if (cursor.moveToFirst()) {
        do {
            Contact contact = new Contact();
            contact.setID(Integer.parseInt(cursor.getString(0)));
            contact.setName(cursor.getString(1));
            contact.setPhoneNumber(cursor.getString(2));
            // Adding contact to list
            contactList.add(contact);
        } while (cursor.moveToNext());
    }

    // return contact list
    return contactList;
}

// Updating single contact
public int updateContact(Contact contact) {
    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put(KEY_NAME, contact.getName());
    values.put(KEY_PH_NO, contact.getPhoneNumber());

    // updating row
    return db.update(TABLE_CONTACTS, values, KEY_ID + " = ?",
            new String[] { String.valueOf(contact.getID()) });
}

// Deleting single contact
public void deleteContact(Contact contact) {
    SQLiteDatabase db = this.getWritableDatabase();
    db.delete(TABLE_CONTACTS, KEY_ID + " = ?",
            new String[] { String.valueOf(contact.getID()) });
    db.close();
}


// Getting contacts Count
public int getContactsCount() {
    String countQuery = "SELECT  * FROM " + TABLE_CONTACTS;
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.rawQuery(countQuery, null);
    cursor.close();

    // return count
    return cursor.getCount();
}

public void Upgrade (SQLiteDatabase db, int oldVersion, int newVersion) {
    String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_CONTACTS + "("
            + KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT,"
            + KEY_PH_NO + " TEXT" + ")";
    db.execSQL(CREATE_CONTACTS_TABLE);
}

// Deleting single contact
    public void deleteTable() {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete("contacts", null, null);
    }
}

回答by Drew

It happens because of the:

它的发生是因为:

db.close();

db.close();

in the methods:

在方法中:

void addContact(Contact contact)

void addContact(Contact contact)

public void deleteContact(Contact contact)

public void deleteContact(Contact contact)

You should not close the connection to the underlying database unless you reallydo not intend to work with it anymore. Use SQLiteOpenHelper:close, when you've finished your work.

除非您真的不打算再使用它,否则不应关闭与基础数据库的连接。使用SQLiteOpenHelper:close,当你完成你的工作。

Moreover, calls to getReadableDatabase()and getWriteableDatabase()return the same database object 99% of a time, and they do notreinitialize database connection closed manually by you.

此外,99% 的时间调用getReadableDatabase()getWriteableDatabase()返回相同的数据库对象,并且它们不会重新初始化您手动关闭的数据库连接。

Don't get fooled by these method names.

不要被这些方法名称所迷惑。

回答by Kailas Bhakade

I would like to suggest you that, dont close database object before complete your database work.

我想建议你,在完成你的数据库工作之前不要关闭数据库对象。

SQLiteDatabase db;
db = this.getWritableDatabase();

or

db = this.getReadableDatabase();

Above both method give us database object using helper class and using this object we can do different actions on database. But in your scenario, I think so you closed database object before complete database operation. So closed after done all operation by using

以上两种方法都使用 helper 类为我们提供了数据库对象,使用此对象我们可以对数据库执行不同的操作。但是在您的场景中,我认为您在完成数据库操作之前关闭了数据库对象。使用完成所有操作后关闭

db.close();

回答by Jonathan Michael Bellfontaine

The onUpgrade is when you made changes to your database (ie adding tables) so there is now a new version of your database. Your:

onUpgrade 是当您对数据库进行更改(即添加表)时,因此现在有一个新版本的数据库。您的:

private static final int DATABASE_VERSION = 1;

is now

就是现在

private static final int DATABASE_VERSION = 2;

Because the database version is now higher newer version the OnUpgrade() method is called and updates the database.

由于数据库版本现在更高,因此调用 OnUpgrade() 方法并更新数据库。

回答by Ruchit Jain

it basically happens because of cursor.close(); since you are closing the cursor object before you are returning its count.

这主要是因为 cursor.close(); 因为您在返回其计数之前关闭了游标对象。

回答by Namikaze Minato

I should have defined int count = cursor.getCount();before closing the database. It seems return cursor.getCount();after closing the database is a useless effort.
At last removing db.close();at the end of delete and remove methods was necessary.
Adding this code instead in handler instead helped alot:

我应该int count = cursor.getCount();在关闭数据库之前定义。return cursor.getCount();关闭数据库后似乎是无用的努力。
最后db.close();在删除和删除方法结束时删除是必要的。
在处理程序中添加此代码反而有很大帮助:

public void closeDB() {
    SQLiteDatabase db = this.getReadableDatabase();
    if (db != null && db.isOpen())
        db.close();
}

Manipulating closefunction inside activity at the end of database usage was better. Thanks to @Drew.
I still can't understand the usage of onUpgradeinside handler ???

close在数据库使用结束时在活动内部操作函数更好。感谢@Drew。
我仍然无法理解onUpgrade内部处理程序的用法???