web-dev-qa-db-fra.com

Android SQLite: tentative de ré-ouvrir un objet déjà fermé

J'essaie d'obtenir certaines données de livre de ma table d'inventaire en fonction de l'ISBN. Cependant, une erreur s’affiche: "tenter de rouvrir un objet déjà fermé". L'erreur ne survient que lorsque je clique sur un objet listView, passe à un autre écran, retourne à cette page via "finish ()", puis essaie de cliquer sur un autre objet listView. J'ai déplacé la String searchEntries[] = InventoryAdapter.getInventoryEntriesByISBN(searchQuery, isbn[position]); de la onClickListener vers la précédente pour la boucle avant la onClickListener et maintenant cela fonctionne. 

Pourquoi cela ne fonctionne-t-il pas si j'essaie d'obtenir GetInventoryEntriesByISBN après avoir repris cette activité à partir d'une autre activité via "finish ()"? 

L'erreur se produit sur SearchResultsScreen:

String searchEntries[] = InventoryAdapter.getInventoryEntriesByISBN(searchQuery, isbn[position]);

et par extension, se produit à InventoryAdapter:

Cursor cursor = db.rawQuery(query, new String[] {ISBN});

SearchResultsScreen.Java

// Set up search array
    for(int i = 0; i < isbn.length; i++)
    {
        searchArray.add(new InventoryItem(isbn[i], InventoryAdapter.getTitleAndAuthorByISBN(isbn[i])));
    }
    Toast.makeText(getApplicationContext(), "searchArray.size()="+searchArray.size(), Toast.LENGTH_LONG).show();

    // add data in custom adapter
    adapter = new CustomAdapter(this, R.layout.list, searchArray);
    ListView dataList = (ListView) findViewById(R.id.list);
    dataList.setAdapter(adapter);

    // On Click ========================================================
    dataList.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                long id) {
            String searchEntries[] = InventoryAdapter.getInventoryEntriesByISBN(searchQuery, isbn[position]);

InventoryAdapter.Java (Parties les plus pertinentes)

public String[] getInventoryEntriesByISBN(String search, String ISBN)
{
    String[] searchEntry = new String [9];
    //Query
    String query = "select * from INVENTORY where ISBN = ?";
    Cursor cursor = db.rawQuery(query, new String[] {ISBN});
    if(cursor.getCount()<1) // title Not Exist
    {
        cursor.close();
        for(int i = 0; i < 9; i++)
            searchEntry[i] = "Not Found";
        return searchEntry;
    }
    cursor.moveToFirst();

    //put data into respective variable
    int publish = cursor.getInt(cursor.getColumnIndex("PUBLISH_DATE"));
    String publishdate = ((Integer)publish).toString();
    String title = cursor.getString(cursor.getColumnIndex("TITLE"));
    String author = cursor.getString(cursor.getColumnIndex("AUTHOR"));
    String callNumber = cursor.getString(cursor.getColumnIndex("CALL_NUMBER"));
    int available = cursor.getInt(cursor.getColumnIndex("AVAILABLE_COUNT"));
    String availablecount = ((Integer)available).toString();
    int inventory = cursor.getInt(cursor.getColumnIndex("INVENTORY_COUNT"));
    String inventorycount = ((Integer)inventory).toString();
    int due = cursor.getInt(cursor.getColumnIndex("DUE_PERIOD"));
    String dueperiod = ((Integer)due).toString();
    int checkoutcount = cursor.getInt(cursor.getColumnIndex("COUNT"));
    String count = ((Integer)checkoutcount).toString();
    //combine variables into one array
    searchEntry[0] = ISBN;
    searchEntry[1] = title;
    searchEntry[2] = author;
    searchEntry[3] = publishdate;
    searchEntry[4] = callNumber;
    searchEntry[5] = availablecount;
    searchEntry[6] = inventorycount;
    searchEntry[7] = dueperiod;
    searchEntry[8] = count;

    cursor.close();
    return searchEntry;
}

public String getTitleAndAuthorByISBN(String ISBN)
    {
        int entriesFound = getNumSearchEntries(ISBN);
        if(entriesFound==0)
            entriesFound = 1;
        String searchEntry;
        //Query
        String query = "select * from INVENTORY where ISBN = ?";
        Cursor cursor = db.rawQuery(query, new String[] {ISBN});
        if(cursor.getCount()<1) // title Not Exist
        {
            cursor.close();
            searchEntry = "Not Found";
            return searchEntry;
        }
        cursor.moveToFirst();
        //put data into respective variable
        String title = cursor.getString(cursor.getColumnIndex("TITLE"));
        String author = cursor.getString(cursor.getColumnIndex("AUTHOR"));
        //combine variables into one String
        searchEntry = title + " / " + author;
        //close cursor and return
        cursor.close();
        return searchEntry;
    }

DataBaseHelper.Java

public class DataBaseHelper extends SQLiteOpenHelper
{   
// Database Version
    private static final int DATABASE_VERSION = 1;

// Database Name
private static final String DATABASE_NAME = "database.db";

// ============================ End Variables ===========================

public DataBaseHelper(Context context, String name, CursorFactory factory, int version) 
{
           super(context, name, factory, version);
}

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

// Called when no database exists in disk and the helper class needs
// to create a new one.
@Override
public void onCreate(SQLiteDatabase _db) 
{
        _db.execSQL(LoginDataBaseAdapter.USER_TABLE_CREATE);
        _db.execSQL(CheckOutDataBaseAdapter.CHECKOUT_TABLE_CREATE);
        _db.execSQL(InventoryAdapter.INVENTORY_TABLE_CREATE);
        _db.execSQL(StatisticsAdapter.STATISTICS_TABLE_CREATE);
}
// Called when there is a database version mismatch meaning that the version
// of the database on disk needs to be upgraded to the current version.
@Override
public void onUpgrade(SQLiteDatabase _db, int _oldVersion, int _newVersion) 
{
        // Log the version upgrade.
        Log.w("TaskDBAdapter", "Upgrading from version " +_oldVersion + " to " +_newVersion + ", which will destroy all old data");


        // Upgrade the existing database to conform to the new version. Multiple
        // previous versions can be handled by comparing _oldVersion and _newVersion
        // values.
        // on upgrade drop older tables
        _db.execSQL("DROP TABLE IF EXISTS " + LoginDataBaseAdapter.USER_TABLE_CREATE);
        _db.execSQL("DROP TABLE IF EXISTS " + CheckOutDataBaseAdapter.CHECKOUT_TABLE_CREATE);
        _db.execSQL("DROP TABLE IF EXISTS " + InventoryAdapter.INVENTORY_TABLE_CREATE);
        _db.execSQL("DROP TABLE IF EXISTS " + StatisticsAdapter.STATISTICS_TABLE_CREATE);

        // Create a new one.
        onCreate(_db);
}

}
9
erad

L'erreur ne se produit que lorsque je clique sur un élément, passe à un autre écran, retourne à cette page via "finish ()", puis essaie de cliquer sur un autre objet listView. 

J'ai déplacé la chaîne searchEntries [] = InventoryAdapter.getInventoryEntriesByISBN (searchQuery, isbn [position]); de la boucle onClickListener à la boucle for précédente avant celle onClickListener et maintenant cela fonctionne.

Le SearchResultsScreen correct est ci-dessous:

SearchResultsScreen.Java

// Set up search array
    final String Entries[][] = new String[isbn.length][9];
    for(int i = 0; i < isbn.length; i++)
    {
        searchArray.add(new InventoryItem(isbn[i], InventoryAdapter.getTitleAndAuthorByISBN(isbn[i])));
        Entries[i] = InventoryAdapter.getInventoryEntriesByISBN(searchQuery, isbn[i]);
    }
    Toast.makeText(getApplicationContext(), "searchArray.size()="+searchArray.size(), Toast.LENGTH_LONG).show();

    // add data in custom adapter
    adapter = new CustomAdapter(this, R.layout.list, searchArray);
    ListView dataList = (ListView) findViewById(R.id.list);
    dataList.setAdapter(adapter);

    // On Click ========================================================
    dataList.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                long id) {
            String searchEntries[] = Entries[position];
2
erad

Vérifiez la connexion à la base de données avant d'exécuter la requête:

if (!dbHelper.db.isOpen()) dbHelper.open();

vous pouvez également utiliser cursor.requery(); pour répéter la même requête.

enfin, vous devez également fermer le curseur et la base de données.

cursor.close();
db.close();

Édité:

J'ai créé la classe DBHelper qui étend la variable SQLiteOpenHelper. Cette classe est la classe interne de la classe DatabaseHelper et cette classe possède les méthodes suivantes.

/** For OPEN database **/
public synchronized DatabaseHelper open() throws SQLiteException {
    dbHelper = new DBHelper(context);
    db = dbHelper.getWritableDatabase();
    return this;
}

/** For CLOSE database **/
public void close() {
    dbHelper.close();
}

Si vous avez encore des doutes, n'hésitez pas à me contacter. Je vous remercie.

14
Pratik Butani

C'est ton problème

    if(cursor.getCount()<1) // title Not Exist
    {
        cursor.close(); 
        for(int i = 0; i < 9; i++)
            searchEntry[i] = "Not Found";
        return searchEntry;
    }
    cursor.moveToFirst();
    cursor.close();

Changer en

  for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
  {
            String title = cursor.getString(cursor.getColumnIndex("TITLE"));
            String author = cursor.getString(cursor.getColumnIndex("AUTHOR"));
            //combine variables into one String
            searchEntry = title + " / " + author;
  } 
1
Raghunandan
public String[] getInventoryEntriesByISBN(String search, String ISBN)
{
    String[] searchEntry = new String [9];
    //Query
    String query = "select * from INVENTORY where ISBN = ?";
    Cursor cursor = db.rawQuery(query, new String[] {ISBN});

Ajoutez SQLiteDatabase db = this.getWritableDatabase(); dans ce code avant d'exécuter la requête brute

0
PsyGik