Search code examples
androidcursorsimplecursoradapter

StaleDataException:Attempted to access a cursor after it has been closed


In my application, I'm using SimpleCursorAdapter to update Listviews. This SimpleCursorAdapter takes data from Cursor object. Here when I close cursor in onCreate method then it's throwing StaleDataException:Attempted to access a cursor after it has been closed. but when I removed this close method on cursor then it didn't happen and it worked well.But if we remove close method on cursor then will it not create memory leakage?

With cursor.close() -

//the columns which we want to show in list view
    private static final String[] columnsToUse = new String[]{
            UserDictionary.Words.WORD,
            UserDictionary.Words.FREQUENCY};

    // array of item ids where above two entries will be saved
    private static final int[] toView = new int[]{
            android.R.id.text1,
            android.R.id.text2};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //TextView displayTextView = (TextView) findViewById(R.id.display_text);

        ListView dictionaryList = (ListView)findViewById(R.id.dictionary_list_view);

        ContentResolver resolver = getContentResolver();
        Cursor cursor = resolver.query(UserDictionary.Words.CONTENT_URI, null, null, null, null);

        cursor.moveToFirst();



        SimpleCursorAdapter dictionaryAdapter = new SimpleCursorAdapter(this, android.R.layout.two_line_list_item,
                cursor, columnsToUse, toView, 0);

        dictionaryList.setAdapter(dictionaryAdapter);
        cursor.close();

throwing - StaleDataException:Attempted to access a cursor after it has been closed

but if I comment this cursor.close() then this error doesn't come -

   //the columns which we want to show in list view
        private static final String[] columnsToUse = new String[]{
                UserDictionary.Words.WORD,
                UserDictionary.Words.FREQUENCY};

        // array of item ids where above two entries will be saved
        private static final int[] toView = new int[]{
                android.R.id.text1,
                android.R.id.text2};

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            //TextView displayTextView = (TextView) findViewById(R.id.display_text);

            ListView dictionaryList = (ListView)findViewById(R.id.dictionary_list_view);

            ContentResolver resolver = getContentResolver();
            Cursor cursor = resolver.query(UserDictionary.Words.CONTENT_URI, null, null, null, null);

            cursor.moveToFirst();



            SimpleCursorAdapter dictionaryAdapter = new SimpleCursorAdapter(this, android.R.layout.two_line_list_item,
                    cursor, columnsToUse, toView, 0);

            dictionaryList.setAdapter(dictionaryAdapter);
           // cursor.close();

Solution

  • This is what Cursor.close() does releases all of its resources and making it completely invalid... if you call Cursor.close() right after the adapter what will the CursorAdapter use?

    To solve it,

    close() your Cursor in onDestroy() or when the listView along with the CursorAdapter will no longer need it.