【发布时间】:2013-12-07 03:58:40
【问题描述】:
我正在使用 GridView 显示一些图像,但我遇到了问题,因为 onClickListener 不适用于第一张图像。我在 SO 发现了一些其他问题,有同样的问题,但我不喜欢他们的“正确答案”,因为他们中的大多数人都采用相同的方法:
基本上,每次调用 getview 时都会实例化视图。这对性能来说很糟糕,而且它们可能会在许多设备中面临内存不足的问题。
在我的例子中,我在 GridView 中显示位于 assets 文件夹中子文件夹内的图像。
我的原始代码存在“第一项”问题(实际上,我的原始代码实现了 viewholder 模式,但这个更简单一些,并且面临同样的问题):
@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;
}
我解决问题的最终代码:
@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;
}
问题已通过移动代码imageView.setLayoutParams(new GridView.LayoutParams(imageWidth, imageWidth)); 得到解决。
但是为什么呢?我不确定。
我在某处(在 SO 中)读到它可能是因为尝试访问尚未膨胀的视图而发生的,并且用户建议使用 getViewTreeObserver(),但我尝试了这种方法并无法解决问题.
因此,我决定对代码进行反复试验,以查看可能出现瓶颈的位置并找到给定的解决方案。
任何人都知道为什么这可以解决问题?
【问题讨论】:
-
这可能会有所帮助[链接] [1]:stackoverflow.com/questions/11778228/…
-
谢谢@anish,但这是我在问题中提到的(恕我直言)错误修复的一个例子。从字面上看,他的解决方法是“最终通过在每次传递中使持有者实例化来解决它,而不是通过标签获取它(这对性能更好,但是哦)。”
getView()可以被多次调用,他绕过了convertView的用处,通过膨胀布局并每次调用getView()两次调用findViewById。在 GridView 中使用图像可能会导致 OutOfMemory 崩溃。 -
添加 LayoutParams 解决您的问题的可能原因是它触发了另一个布局传递。这似乎表明您的视图正在其他地方重用,并且它的 OnClickListener 正在被替换。我记得我自己也遇到过这种奇怪的行为,但不太记得我是如何解决它的。我会看看我是否能弄清楚它与哪个项目有关。
-
好的,谢谢!我会很感激这些额外的信息。
-
以防万一,这正常吗:
GridView.LayoutParams(imageWidth, imageWidth)?应该是:GridView.LayoutParams(imageWidth, **imageHeight**)还是只是复制/粘贴错误?
标签: android gridview onclicklistener