2014-01-09 14 views
5

我是Android开发新手,看书Hello Android。它使用了一个Sudoku示例,我所指的代码是here.我是否在每次通话中使整个屏幕无效?

在此onTouchScreen中,它调用select方法,该方法调用invalidate两次。问题是,在invalidating之后是onDraw方法吗?所以才会在这种情况下,我的选择方法中,它会做

  1. 无效
  2. 调用的OnDraw
  3. 做一些东西
  4. 无效
  5. 调用的OnDraw

这究竟是怎么它会发生,而且,整个屏幕会重新生成吗?所有的数字和提示等,因为从该书作者说

在这个例子中的早期版本,我无效整个 屏幕,只要游标被感动了。因此,在每一个键 按下,整个谜题必须重绘。这导致它显着地落后于 。切换代码以仅使最小的 矩形变为无效,这使得其运行得更快。

他究竟想在这里说什么?

新增信息

我加了一些日志中的onDraw方法,一些在起跑线,有的在for循环。每当我触摸一个新的矩形时,所有的日志都会被调用。这是否意味着整个屏幕都会重新填充,因为onDraw中的所有代码都会重新执行?

回答

5

海妖

问:但是有关日志的,当然,如果越来越执行我的循环意味着什么,所有的canvas.draw将会得到执行呢?答:是的,整个绘图将在您的示例代码中执行。您必须自己优化渲染过程,采用onDraw方法。

问:系统如何知道,哪块代码将“只”重绘脏区?
- 答:Canvas::getClipBounds会给你一个肮脏的矩形,你应该画一些东西。
在你的for looponDraw里面,比较脏矩形和你想绘制的矩形。如果它们不相交,则执行continue

但请记住,如果您有几个区域设置为脏,返回的矩形将是所有脏区域的联合。
请参阅下面的以下两个问题:
Getting the dirty region inside draw()
Android: invalidate(dirty)

希望这会帮助你。

==========================

作者是正确的。但是这仍然可以优化。

调用invalidate(Rect)将自动设置画布的剪辑区域。 (这就是为什么canvas.getClipBounds()可以返回该区域)。
然后,在onDraw()期间,任何绘制出剪辑区域的内容都将被忽略。它们不会出现在屏幕上,所以它减少了绘图的时间。
但是忽略它们仍然需要开销。因此,对于图形密集型应用程序,如果您事先排除它们,则可以更好地优化onDraw()

您可以在Android的KeyboardView中找到一个优化onDraw()的好例子,它提供了Android输入法的视图。 http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/inputmethodservice/KeyboardView.java

+0

@ ZhenghonghWang我不确定我是否正确地得到它,我设置了一些脏东西,并在我的代码中,在onDraw方法中,我没有明确地获取脏部分。所以你是说在我的情况下,整个事情会得到渲染?因为根据作者的说法,他已经以最佳方式做到了,而且只会渲染脏部分。 – Kraken

+0

是的,你提到的作者是正确的。但绘图过程可以更好地优化。我更新了我的答案。 –

+1

使用rect失效不会改变打开硬件加速的画布剪辑边界。无论传递给Invalidate的矩形如何,整个视图总是重绘。 – jjxtra

0

在代码中,你所谈论的无效是这样的:

invalidate(selRect); 

如果是他只调用此选定矩形的onDraw selRect

只有invalidate();重新绘制孔屏幕。

希望它有帮助。

+0

请按照对其他答案的意见,并提供我的问题的答案请。谢谢。 – Kraken

0

在此示例中,您应该注意到invalidate()调用具有Rect作为参数。这意味着只有这个视图区域变脏,并且将被系统重新绘制。

调用invalidate()不会立即触发onDraw()方法。系统只在他想重新绘制视图时才决定。

从Android文档:

如果视图是可见的,的onDraw(android.graphics.Canvas)将在未来的某个时刻被称为 。

知道的是,select方法里面,这可能会发生: 1.无效查看 2的一小部分做一些东西 3.无效查看 4.论文2的另一小部分部分视图正在重绘

希望有所帮助。

+0

我在onDraw方法中添加了一些日志,其中一些在起始处,一些在for循环中。每当我触摸一个新的矩形时,所有的日志都会被调用。这不意味着整个屏幕重新填充? – Kraken

+0

当我说“整个屏幕”时,我的意思是整个视图。 – Kraken

+0

整个视图并未完全重绘。在您的设备的开发人员选项中有一个非常有用的选项,可以让您在更新时屏幕闪烁。启用此选项,然后尝试触摸一个矩形,只有这个矩形(和第二个)应该弹起 – pdegand59

2

这是直接从View documentation

绘图通过遍历树和渲染相交无效区域的每个视图进行处理。因为树是按顺序遍历的,这意味着父母会在他们的孩子之前(即在他们的后面)绘制,并且兄弟姐妹按照它们出现在树中的顺序绘制。如果你为一个View设置了一个可绘制的背景,那么这个View就会在你调用它的onDraw()方法之前为你绘制。

注意框架不会画意见不在无效region.`

从我明白,一旦你的图绘,第一次,如果形成了家长和孩子一棵树物体以及它们在屏幕上的位置。当你通过一个指定的区域使其无效时,检查该树是否在该区域受到影响,并且只有那些节点才会被调用来绘制。

现在我也不明白的是,在这个例子中,唯一的视图是拼图。我不确定如何优化单个视图的绘图。检查是否在文中进一步讨论。

如果不是,那么我的理论是画布对象(矩形)也是上述树的一部分,只有那些部分,即指定区域中的矩形被绘制。

更重要的是,在使用区域无效与完全无效后,您是否看到任何改进?

1

即使您多次调用invalidate,onDraw方法也只会被调用一次。基本上,当视图失效时,onDraw会在RunLoop方法内被调用。这意味着如果在将控制权交还给runloop之前多次使视图无效,则视图将仅重绘一次。 请注意,如果您使视图的两个不同的区域无效,则系统将在重新绘制视图之前尝试使这些区域的联合。