I'm using a GridView to show some images and I had a problem, as the onClickListener wasn't working for the first image. I found some other questions here at SO with the same problem, but I don't like their "correct answers", as most of them take the same approach of:
Basically, instantiating the view every time getview is called. This is awful for performance and they will probably face out-of-memory issues in many devices.
In my case, I display in the GridView the images located inside a sub-folder in the assets folder.
My original code with the "first item" issue (actually, my original code implemented the viewholder pattern, but this one is a bit simpler and faces the same issue):
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
imageView = new ImageView(_activity);
} else {
imageView = (ImageView) convertView;
}
// get screen dimensions
AssetManager assetManager = _activity.getAssets();
InputStream assetIn = null;
try {
assetIn = assetManager.open(_assets_subdir + File.separator + _filePaths.get(position));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Bitmap image = BitmapFactory.decodeStream(assetIn);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(new GridView.LayoutParams(imageWidth, imageWidth));
imageView.setImageBitmap(image);
// image view click listener
imageView.setOnClickListener(new OnImageClickListener(position));
return imageView;
}
My final code solving the issue:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
imageView = new ImageView(_activity);
imageView.setLayoutParams(new GridView.LayoutParams(imageWidth, imageWidth));
} else {
imageView = (ImageView) convertView;
}
// get screen dimensions
AssetManager assetManager = _activity.getAssets();
InputStream assetIn = null;
try {
assetIn = assetManager.open(_assets_subdir + File.separator + _filePaths.get(position));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Bitmap image = BitmapFactory.decodeStream(assetIn);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageBitmap(image);
// image view click listener
imageView.setOnClickListener(new OnImageClickListener(position));
return imageView;
}
The issue was solved moving the code imageView.setLayoutParams(new GridView.LayoutParams(imageWidth, imageWidth));
.
But why? I'm not sure.
I read somewhere (in SO) that it could be happening because of trying to access a view that has not been inflated yet, and the user recommended using getViewTreeObserver()
, but I tried that approach and couldn't fix the problem.
So, I decided to trial-and-error the code to see where to bottleneck could be and found the given solution.
Anyone knows why is this solving the problem?