处理依赖于 View 维度的繁重操作

Handling heavy operations that depend on `View`'s dimensions

我正在实施一个必须从磁盘加载 Bitmap 的自定义 ImageViewBitmap 应该精确缩放,它的宽度必须等于父布局分配给我的 ImageView 的最终宽度,并且计算高度以保持纵横比。

所以,问题是 View 生命周期中什么地方适合放置依赖于布局完成后已知的 View 维度的繁重操作?

(但我想保持简单,不使用线程。)

  1. 很可能将该代码放在 onDraw() 方法中是个坏主意, 因为它应该尽可能高效。另一方面,我的 ImageView 不太可能调整大小,因此它只会杀死 first onDraw()的表现,不会影响后续 调用 onDraw()。所以我不确定这个选项。
  2. 我可以把它放在 onLayout(boolean changed, int l, int t, int r, int b) 执行我的结尾 重代码 if (changed == true)。这是个好主意吗?
  3. 我看到的第三个选项是在 onSizeChanged() 回调中进行。 我唯一关心的是这个回调是否保证 每个实际视图的大小更改仅调用一次。我倾向于使用 这个选项,因为在我的测试中它工作正常。

有人可以对此发表见解吗?

选项 2 和 3 都可以让您获得视图的正确尺寸。

onDraw() 仅在 onLayout() 之后调用。您可以在 onLayout() 中获取尺寸,最好避免在 onDraw() 中做任何不必要的工作。所以我会选择选项 2 或选项 3。

还要注意 onSizeChanged() 有时被称为零。伊恩 in this thread:

Be aware too that onSizeChanged() is sometimes called with parameters of zero -- check for this case, and return immediately (so you don't get a divide by zero when calculating your layout, etc.). Some time later it will be called with the real values.

另一种选择是使用 View.post()

将可运行对象添加到视图的队列中

引用和示例 from this thread:

The UI event queue will process events in order. After setContentView() is invoked, the event queue will contain a message asking for a relayout, so anything you post to the queue will happen after the layout pass

final View view=//smth;
...
view.post(new Runnable() {
            @Override
            public void run() {
                view.getHeight(); //height is ready
            }
        });

使用这种方法,我们可以确保我们的代码只执行一次。