【问题标题】:Android: findViewById of an ImageView (custom adapter)Android:ImageView 的 findViewById(自定义适配器)
【发布时间】:2011-03-20 15:01:54
【问题描述】:

我一直在尝试重新设置 ImageView 的大小。 我正在使用自定义适配器。

View row = convertView;
if (row == null) {
    LayoutInflater inflater =  (LayoutInflater)
        context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    row = inflater.inflate(R.layout.grid_item, null);
}

thumb = (ImageView) row.findViewById(R.id.bookThumb);

当我使用 ImageView thumb = (ImageView) row.findViewById(R.id.bookThumb);在自定义适配器内部它工作得很好,但是因为它循环遍历每一行,所以滚动非常慢。

所以...我现在正在尝试获取 thumb = (ImageView) row.findViewById(R.id.bookThumb);从我的 Main Activity 并设置它的大小,但我得到 Null,因此应用程序强制关闭。

试过了:

LinearLayout layout = (LinearLayout) findViewById(R.id.gridLayout);
ImageView thumbRow = (ImageView)layout.findViewById(R.id.bookThumb);

也试过了:

// gv is the gridview (R.id.gridview)
ImageView thumbRow = (ImageView)gv.findViewById(R.id.bookThumb);

总是为空。

感谢任何帮助!感觉我错过了一些愚蠢的东西:)

【问题讨论】:

  • 尝试使用hierarchyviewer 来查看您的视图层次结构实际上是什么样的。
  • 您在主要活动中的哪个位置执行此操作?是在调用 setContentView 之后吗?
  • @Gil,我会尝试使用它...谢谢。 @slund,是的,之后。此外,检查 android.R 的任何错误导入,使用 /> 而不是 关闭 ImageView,并且基本上完成了我在 google 上找到的所有内容 :)
  • 当您使用适配器时,我想有很多元素的 ID 为 R.id.bookThumb。如果视图层次结构的某个分支包含许多具有相同 id 的元素,并且您从该分支的根调用 findViewById(),它将返回 null,因为它不知道您想要哪个。
  • @bigstones - 你当然是对的。我的问题是如何为所有 bookThumb imageviews 设置它?当我通过适配器设置宽度时,它可以工作,但滚动速度很慢。

标签: android android-gridview


【解决方案1】:

我认为问题出在两个地方。

首先解决原始问题。由于 findViewById 调用,您的适配器很慢。您利用了回收的视图,这很好,但您仍然遍历视图以获取缩略图。有一种技术,非正式地称为 ViewHolder,基本上使它更像是直接调用。

因此,不仅可以使用回收的视图作为开始填充数据的地方,还可以为其附加一些结构,以便您可以预取要操作的元素

if (row == null) {
    LayoutInflater inflater =  (LayoutInflater)
        context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    row = inflater.inflate(R.layout.grid_item, null);
    row.setTag(row.findViewById(R.id.bookThumb));

}

thumb = (ImageView) row.getTag();

这里我们直接通过变量调用,没有进行遍历。这应该快得多。

还有第二个问题,NullPointerExcepton。

我认为这是 id 的模糊性与您在主要活动中调用 findViewById 的点混合。你不能在你的 mainActivity 中做得很好,尤其是在涉及滚动的情况下,因为你必须拦截在适配器视图中渲染的调用。大多数回调已经在主线程上,因此两个事情不能在该线程上同时发生。

因此,在您调用 findViewById() 时,适配器可能还没有运行并将该视图附加到层次结构中。如果确实如此,它可能还没有完成对它的操作。

在处理第二个问题之前,我会尝试加速您的适配器,因为我不确定在不完全放弃使用适配器视图的情况下是否可以安全或准确地执行此操作。

【讨论】:

  • 格雷格,感谢您解释清楚的答案!不幸的是,它并没有影响我的速度问题。导致我的速度问题的原因是我编写的一个函数,它根据用户屏幕大小和一些设置更改缩略图大小。我知道这是导致主要减速的原因,因为当我禁用它时,gridview 滚动平滑(就像我在我的应用程序中拥有的列表视图一样)。我觉得很奇怪不可能使用代码从任何我想要的地方更改 ImageView 的 XML...我只想更改它的宽度和高度..
  • 但是您不能预先更改缩略图吗?您不必在 UI 线程上执行此操作。 imageview 也会缩放图像(不幸的是在 UI 线程上)。您看到了多少减速?
  • 与我不进行这些计算的列表视图相比,速度没有那么慢,但很明显。问题是我在运行时计算缩略图大小,因为用户可以选择他想要 2 列还是 3 列。有了这个,我也考虑了屏幕分辨率。
  • 我猜我还是不明白。我认为您可以通过网格视图完成所有这些操作(它不如列表视图快,但通常可以容忍)。我唯一能说的是如果网格视图太慢,那么不要使用适配器视图并使用原始绘图自己进行渲染。这将使您的渲染速度更快,但代价是更多的实施和更多的维护。
  • 我会尽量让代码更小更高效。删除一些 If 和 else :) 谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多