Search code examples
androidsqlitelistviewonresumeonpause

App crashes between onPause and onResume Listview issue


I have a listview activity which populates data through an sqlite database; however, whenever I enter onPause and then go into onResume my app crashes and I receive this error: "java.lang.IllegalStateException: trying to requery an already closed cursor android.database.sqlite.SQLiteCursor@418106a8". Would anyone know how to stop this? Is there a method I have to call in onPause?

        @Override
protected void onResume() {
    super.onResume();
    uGraduateListAdapter = new ArrayAdapter<String>(ListOfAlarms.this, android.R.layout.simple_list_item_1, populateList());
    listOfAlarms.setAdapter(uGraduateListAdapter);
    Log.i(TAG, "Resume was called");
}

@Override
protected void onPause() {
    super.onPause();

    Log.i(TAG, "Pause was called");
    sqliteDatabase.close();
}



public List<String> populateList(){

        // We have to return a List which contains only String values. Lets create a List first
        List<String> uGraduateNamesList = new ArrayList<String>();

        // First we need to make contact with the database we have created using the DbHelper class
        AndroidOpenDbHelper openHelperClass = new AndroidOpenDbHelper(this);

        // Then we need to get a readable database
         sqliteDatabase = openHelperClass.getReadableDatabase();

        // We need a a guy to read the database query. Cursor interface will do it for us
        //(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
         cursor = sqliteDatabase.query(AndroidOpenDbHelper.TABLE_NAME_ALARM, null, null, null, null, null, null);
        // Above given query, read all the columns and fields of the table

        startManagingCursor(cursor);

        // Cursor object read all the fields. So we make sure to check it will not miss any by looping through a while loop
        while (cursor.moveToNext()) {
            // In one loop, cursor read one undergraduate all details
            // Assume, we also need to see all the details of each and every undergraduate
            // What we have to do is in each loop, read all the values, pass them to the POJO class
            //and create a ArrayList of undergraduates

            String alarmName = cursor.getString(cursor.getColumnIndex(AndroidOpenDbHelper.COLUMN_NAME_ALARM_NAME));
//            String ugUniId = cursor.getString(cursor.getColumnIndex(AndroidOpenDbHelper.COLUMN_NAME_UNDERGRADUATE_UNI_ID));
            String alarmTotalTime = cursor.getString(cursor.getColumnIndex(AndroidOpenDbHelper.COLLUMN_ALARM_TOTALTIME));

            // Finish reading one raw, now we have to pass them to the POJO
            TestAlarm ugPojoClass = new TestAlarm();
            ugPojoClass.setTitle(alarmName);

            ugPojoClass.setTotalTime(alarmTotalTime);

            // Lets pass that POJO to our ArrayList which contains undergraduates as type
            pojoArrayList.add(ugPojoClass);

            // But we need a List of String to display in the ListView also.
            //That is why we create "uGraduateNamesList"
            uGraduateNamesList.add(alarmName);
        }

        // If you don't close the database, you will get an error
        sqliteDatabase.close();

        return uGraduateNamesList;
    }

Solution

  • You are using deprecated methods (startManagingCursor()), which is dangerous.

    How I see what happens: when you close your database (twice actually: in populateList() and onPause()), your cursors to this database become invalid. But since you called startManagingCursor(), your Activity retains your cursors and tries to call requery() on them when restarting, which throws the error.

    Try not calling startManagingCursor() at all, just cursor.close() when you're done with it. Or you can migrate to newer LoaderManager altogether.