Android "attempted to access a cursor after it has been closed"
adapter, android, android-cursor, android-gridview, android-imageview
Solution
Android “attempted to access a cursor after it has been closed”
While you are working / accessing to data in `Cursor`, it needs to be opened!
Generally is recommended to close any datasources and cursors in Activity's life-cycle method either `onStop()` or `onDestroy()` method.
Basic example:
public void onDestroy() {
super.onDestroy();
if (cursor != null) {
c.close();
}
if (db != null) {
db.close();
}
}
Problem
I'm trying to adapt the HelloGridView example so that I can show image thumbnails of images stored on the SD instead of images in the res/drawable. The idea is to create a list with the images first in the ImageView.initialize() function and the use it pretty much exactly as in the example. I'm having trouble with my cursor, first I tried to have it as private in the Imageview.initialize() function (it's only commented away so you can see where I had it) since to me it seems like it is only being used there but then I got the error "Attempted to access a cursor after it has been closed." in the onCreate() function at the line gridview.setAdapter(imageAdapter); so this line obviously uses it somehow. Next try was to have the cursor as "global" and close it after that line instead but i get the same error but now when I'm leaving the onCreate(). This is how the code is now and I have no clue what to do. Also if you find anything else that looks odd please let me know since I'm very very new at android and java. ``` package se.mmarks.hellogridview; import java.util.ArrayList; import android.app.Activity; import android.content.Context; import android.database.Cursor; import android.os.Bundle; import android.provider.MediaStore; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView; import android.widget.Toast; public class MainActivity extends Activity { private Cursor imagecursor; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); GridView gridview = (GridView) findViewById(R.id.gridview); ImageAdapter imageAdapter = new ImageAdapter(this, imagecursor); imagecursor = imageAdapter.initialize(); gridview.setAdapter(imageAdapter); /* setAdapter needs the cursor, * this is why it is closed here and not in ImageAdapter.initialize() */ imagecursor.close(); gridview.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { Toast.makeText(MainActivity.this, "" + position, Toast.LENGTH_SHORT).show(); } }); } } class ImageAdapter extends BaseAdapter { private ArrayList<ImageView> images = new ArrayList<ImageView>(); Cursor imagecursor = null; private Context mContext; public ImageAdapter(Context c, Cursor cursor) { mContext = c; imagecursor = cursor; } public Cursor initialize() { final String[] columns = { MediaStore.Images.Thumbnails._ID }; imagecursor = null; try { imagecursor = mContext.getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null, null, null); } catch(Exception e) { e.printStackTrace(); } if(imagecursor != null){ int image_column_index = imagecursor.getColumnIndex(MediaStore.Images.Thumbnails._ID); int count = imagecursor.getCount(); for (int i = 0; i < count; i++) { imagecursor.moveToPosition(i); int id = imagecursor.getInt(image_column_index); ImageView imageItem = new ImageView(mContext); imageItem.setId(id); imageItem.setImageBitmap( MediaStore.Images.Thumbnails.getThumbnail(mContext.getContentResolver(), id, MediaStore.Images.Thumbnails.MICRO_KIND, null)); images.add(imageItem); } //imagecursor.close(); } return imagecursor; } @Override public int getCount() { return imagecursor.getCount(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { // if it's not recycled, initialize some attributes imageView = images.get(position); imageView.setLayoutParams(new GridView.LayoutParams(85, 85)); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageView.setPadding(8, 8, 8, 8); } else { imageView = (ImageView) convertView; } return imageView; } } ```