Search code examples
javaandroidsqlitecursorout-of-memory

Android sqlite cursor - out of memory


I am trying to debug an 'out of memory' error that I am experiencing, so to condense my example for the purpose of reaching out for help, I have a button, when clicked it queries the db and returns all the values into an ArrayList, the ArrayList is then used to populate a RecyclerView. This is successful, however if I press the button a second time, the 'out of memory' error occurs. The query returns a very large amount of data, and from the log I can see that with just 1 press of the button, not much memory is available (running on an emulator). I came to that conclusion from this line in the log:

com.wizzkidd.myapp D/dalvikvm: GC_FOR_ALLOC freed 1459K, 2% free 91444K/93016K, paused 40ms, total 40ms

and, as previously explained, the second press of the button gives this error:

com.wizzkidd.myapp E/dalvikvm-heap: Out of memory on a 152-byte allocation.

The error is pointing to my database helper class, more specifically, this section of code:

public List<MyInfo> getAllFromDb() {
    List<MyInfo> myArrayList= new ArrayList<MyInfo>();   
    String selectQuery = "SELECT * FROM myTable";
    SQLiteDatabase sqLiteDatabase = this.getReadableDatabase();
    Cursor cursor = sqLiteDatabase.rawQuery(selectQuery, null);
    try {
        if (cursor.moveToFirst()) {
            do {
                MyInfo myInfo = new MyInfo();                                      
                myInfo.setTitle(cursor.getString(0));
                myInfo.setDescription(cursor.getString(1));
                myArrayList.add(myInfo);
            } while (cursor.moveToNext());
        }
    } catch (Exception e) {
        Log.d(TAG, "Error while trying to get data from database");
    } finally {
        if (cursor != null && !cursor.isClosed()) {
            cursor.close();
        }
    }
    return tvGuideInfoList;
}

I have researched previous articles here on SO and the majority of answers say that the cursor must be closed in the finally block. But as you can see above, I am already doing this.


Solution

  • @antlersoft pointed me in the right direction, because I needed to clear/empty the data in my adapter that was used to fill my RecyclerView.

    I came up with this quick method which allowed me to create a blank ArrayList, for MyViewAdapter which I then use it for the RecyclerView. I believe by filling the adapter with a blank ArrayList, it forced the Garbage Collection to clean up the previous data, thus allowing me to have a fresh pool of memory ready for the next fill.

    private void clearRecyclerView() {
            myViewAdapter = new MyViewAdapter(activity, new ArrayList());
            myRecyclerView.setAdapter(myViewAdapter);
            myViewAdapter.notifyDataSetChanged();
    }