tags:

views:

422

answers:

1

I have an app on the market that displays all photos from the user's SDcard in a gallery. Initially I had out of memory issues, but alleviated those by increasing the inSampleSize in the BitmapFactory options. However, I still have intermittent reports of images not displaying, in some cases none at all. There seems to be a larger proportion of Droid Eris users having problems. Here is the method that loads all photos and the accompanying ImageAdapter:

    private void loadAllPhotos() {
    setContentView(R.layout.add_pictures);      
    String[] projection = {MediaStore.Images.Thumbnails._ID};
    cursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
            projection, 
            null,       
            null,
            MediaStore.Images.Thumbnails.IMAGE_ID);
    column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID);
    int size = cursor.getCount();
    if (size == 0) {
        Toast.makeText(thisContext, "Can't find pics on SDcard.", Toast.LENGTH_SHORT).show();
    }
    g = (Gallery) findViewById(R.id.gallery);
    g.setAdapter(new ImageAdapter(this));  
}

The ImageAdapter:

public class ImageAdapter extends BaseAdapter {
    int mGalleryItemBackground;
    public ImageAdapter(Context c) {
        mContext = c;
        TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
        mGalleryItemBackground = a.getResourceId(R.styleable.Gallery1_android_galleryItemBackground, 0);
        a.recycle();
    }
    public int getCount() {
     int cursorCount = mCursor.getCount();
      return cursorCount;
    }
    public Object getItem(int position) {
        return position;
    }
    public long getItemId(int position) {
        return position;
    }
    public View getView(int position, View convertView, ViewGroup parent) {
      ImageView i = new ImageView(mContext);
      System.gc();
      if (convertView == null) {                                        
         try {
             String [] proj={MediaStore.Images.Media.DATA};
             mCursor = managedQuery( MediaStore.Images.Media.EXTERNAL_CONTENT_URI,proj, null, null, null); 
             column_index = mCursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
             mCursor.moveToPosition(position);
             filename = mCursor.getString(column_index);
             if (filename.endsWith(".jpg") || filename.endsWith(".png")) {
                 BitmapFactory.Options options = new BitmapFactory.Options();
                 options.inSampleSize = 15;
                 Bitmap bm = BitmapFactory.decodeFile(filename, options);
                 i.setImageBitmap(bm);
                 i.setScaleType(ImageView.ScaleType.FIT_XY);
                 i.setLayoutParams(new Gallery.LayoutParams(150, 150));
                 i.setBackgroundResource(mGalleryItemBackground); 
                 System.gc();
             }
         } catch (Exception e) { 
         } 
      }
           return i;
    } 
  } 
A: 

If you have not done so already, integrate Flurry or DroidDrop or something to collect exceptions, as they may shed some light on your problem.

Also:

  1. Please recycle your Views! You are creating a new ImageView on every getView() call, which is not helping your GC situation.
  2. You are calling the same managedQuery() on every getView() call, which is horrible. Do that once, please.
  3. You seem to be accessing mCursor in getCount() before it is initialized in getView().
  4. column_index should always be 0 in the way you are calling managedQuery(), so you should not need to use getColumnIndexOrThrow(). Even if you want to use that, only do that once, when you make your single managedQuery() call.

Whether any of that will clear up your Droid Eris problems, though, I cannot say.

CommonsWare
Thanks very much for the feedback. I already use custom error reporting that allows users to email me the stack trace when an exception occurs.I'll make the changes you suggest and see how things go.
polyclef