何时需要在视图上执行 invalidate()?

Posted

技术标签:

【中文标题】何时需要在视图上执行 invalidate()?【英文标题】:When it's necessary to execute invalidate() on a View? 【发布时间】:2012-05-25 17:29:14 【问题描述】:

我对@9​​87654321@ 的回答刚刚被接受,但我开始想知道什么时候需要使视图无效,什么时候不需要?

经过一番思考,我意识到它应该或多或少地像这样工作:

“一切”的实际绘制发生在onResume() 之后 在“空闲”时间可以重绘屏幕的某些部分,但只能重绘 invalidated 的部分(以及下面的所有内容)

因此,如果我在onResume() 之后更改某些内容(例如,作为对按钮单击的响应,我应该将invalidate() 更改为更改后的View)。

但是,根据this question 中的scana 所说,它肯定比这更复杂,并且在某些情况下取决于使用的方法。

例如关于是否使用

lastClicked.setImageBitmap();

lastClicked.setImageResource();

那么,什么时候需要在视图上执行 invalidate() 以及它是如何真正工作的?

【问题讨论】:

【参考方案1】:

(请考虑接受一些答案)

通常,invalidate() 表示“在屏幕上重绘”并导致调用视图的 onDraw() 方法。因此,如果发生变化并且需要在屏幕上反映出来,您需要致电invalidate()。但是,对于内置小部件,您很少(如果有的话)需要自己调用它。当您更改小部件的状态时,内部代码将根据需要调用invalidate(),您的更改将反映在屏幕上。例如,如果你调用TextView.setText(),在做了很多内部处理(文本是否适合屏幕,是否需要省略等)之后,TextView 会在setText() 返回之前调用invalidate()。对于其他小部件也是如此。

如果您实现自定义视图,则需要在支持模型更改并且需要重绘视图时调用invalidate()。它也可以用来创建简单的动画,你改变状态,然后调用invalidate(),再次改变状态等等。

【讨论】:

要完成这个答案,我想说很多时候检查您可能在小部件上使用的各种方法的代码以了解何时存在无效调用并按顺序实施布局尽量减少它们。例如,如果您有一个复杂的布局,则带有 wrap_content 的单个 TextView 将始终在每次调用 setText() 结束时使您的所有布局无效(),另一方面,如果您设法仅获得固定尺寸,则仅视图内的文本将随着更加流畅的 GUI 的结果而改变。【参考方案2】:

通常,系统会自动为您的小部件处理调整大小、隐藏、显示和大量其他事情,但如果绘制像素或支持数据的底层缓冲区已更改或陈旧(您将图像资源交换为视图或原始数据集更改)。发生这种情况是因为操作系统无法知道数据以它所做的特定方式更改。

在处理绘图的这些情况下,您必须使用 Widget.invalidate() 告诉系统其底层数据状态不佳,并且重新绘图会排队等待正如你提到的主线程。根据系统实现和 android 版本,系统跟踪的更改会有所不同,但我通常做的是假设系统资源(字节数组、字符数组、资源索引、在上下文上手动绘制)没有被跟踪并且需要一个 invalidate,其他一切都将由系统处理。

【讨论】:

【参考方案3】:

请记住,在屏幕上绘图是一个频繁的过程,每当您更新视图时,都应该传播并重绘该更改以通知此类更改。 invalidate() 是一种触发方法,表示强制重绘您希望显示更改的任何视图。

【讨论】:

【参考方案4】:

当我想绘制 textPaint 时遇到了这个问题! 我的代码是

    canvas.drawPaint(textPaintNumber)
    canvas.drawText("MyText", 30F, 63F, textPaintNumber)

我清除了第一个 lint,问题就解决了

    canvas.drawText("MyText", 30F, 63F, textPaintNumber)

【讨论】:

以上是关于何时需要在视图上执行 invalidate()?的主要内容,如果未能解决你的问题,请参考以下文章

在vc++中 OnDraw()函数和 Invalidate()函数起啥作用

Winforms:如何加速 Invalidate()?

MFC中的Invalidate、OnDraw、OnPaint函数的作用、区别和联系?

仅更新视图的一部分而不使用 invalidate(Rect)

检测主视图控制器和详细视图控制器何时都在屏幕上?

Invalidate 未调用自定义视图类的 onDraw