[Android] SurfaceView相关知识笔记SurfaceView相关知识笔记本文为[Android] SurfaceView使用实例的辅助
[Android] SurfaceView相关知识笔记
SurfaceView相关知识笔记
本文为"[Android] SurfaceView使用实例"的辅助文章。
本文由4部分内容组成,前3部分取自网络,原文贴出,第4部分为Sodino原创码出。请仔细阅读前3部分后再阅读第4部分"4.为何SurfaceView能够在非UI线程中刷新界面?"
-------------------------------------------------
以下内容出自网络。
1.Surface、Window、View、SurfaceView
http://stackoverflow.com/questions/4576909/understanding-canvas-and-surface-concepts
A Surface is an object holding pixels that are being composited to the screen.Every window you see on the screen (a dialog, your full-screen activity, the status bar) has its own surface that it draws in to, and Surface Flinger renders these to the final display in their correct Z-order. A surface typically has more than one buffer (usually two) to do double-buffered rendering: the application can be drawing its next UI state while the surface flinger is compositing the screen using the last buffer, without needing to wait for the application to finish drawing.
A window is basically like you think of a window on the desktop. It has a single Surface in which the contents of the window is rendered. An application interacts with the Window Manager to create windows; the Window Manager creates a Surface for each window and gives it to the application for drawing. The application can draw whatever it wants in the Surface; to the Window Manager it is just an opaque rectangle.
A View is an interactive UI element inside of a window.A window has a single view hierarchy attached to it, which provides all of the behavior of the window.Whenever the window needs to be redrawn (such as because a view has invalidated itself), this is done into the window's Surface. The Surface is locked, which returns a Canvas that can be used to draw into it. A draw traversal is done down the hierarchy, handing the Canvas down for each view to draw its part of the UI. Once done, the Surface is unlocked and posted so that the just drawn buffer is swapped to the foreground to then be composited to the screen by Surface Flinger.
A SurfaceView is a special implementation of View that also creates its own dedicated Surface for the application to directly draw into (outside of the normal view hierarchy, which otherwise must share the single Surface for the window). The way this works is simpler than you may expect -- all SurfaceView does is ask the window manager to create a new window, telling it to Z-order that window either immediately behind or in front of the SurfaceView's window, and positioning it to match where the SurfaceView appears in the containing window.If the surface is being placed behind the main window (in Z order), SurfaceView also fills its part of the main window with transparency so that the surface can be seen.
2.Relationship between Surface and Canvas
http://stackoverflow.com/questions/3370212/relationship-between-surface-and-canvas-android?lq=1
A surface is a buffer. A Canvas holds the drawing.
Views are not attached to the Canvas nor the Surface. The window is tied to a Surface and
the ViewRoot asks the Surface for a Canvas that is then used by the Views to draw onto.
3. 7 Questions
http://www.mail-archive.com/android-framework@googlegroups.com/msg01901.html
> 1. what is the relationship between ViewRoot and View class.
The ViewRoot is the root of each view hierarchy. Like you said, there
is one ViewRoot per window. The ViewRoot is responsible to handling
the layout and drawing of the view hierarchy. The view hierarchy is
made of Views and ViewGroups. A ViewGroup is a special View that can
contain other Views.
> 2. Is all view ,its children's view and their viewRoot share the same
> canvas for draw?
Yes, but that Canvas might change on every drawing operation. The
ViewRoot acquires a Canvas from the underlying Surface and hands that
Canvas to the top-level View.
> 3. What is the relationship within View, canvas and Surface. To my
> thinking, every view will be attached a canvas and surface.
No, the Views are not attached to the Canvas nor the Surface. The
window is tied to a Surface and the ViewRoot asks the Surface for a
Canvas that is then used by the Views to draw onto.
> 4. canvas hold the bitmap for view, will the actual view drawn data will
> be in canvas' bitmap.
Yes.
> 5. After View draw its data to canvas, ViewRoot
> will call surface.unlockCanvasAndPost(canvas) to schedule
> surfaceFlinger::composeSurfaces() which do the actually display to
> display panel.
Yes.
> 6. Where is the drawn data in canvas transfer to surface front buffer or
> backbuffer? I cannot find the code to do that.
It's done by
SurfaceFlinger.
> 7. Do different views within the same ViewRoot share the same surface?
Yes, except for SurfaceViews.
以上为源文拷贝。
---------------------------------------------------------------4.为何SurfaceView能够在非UI线程中刷新界面?
把这个问题分解为两部分:
4.1 普通的View是如何刷新界面的?
查看ViewRoot.java代码,可以发现界面的刷新操作是在方法draw(boolean fullRedrawNeeded)中完成的。
仔细阅读代码,发现其刷新界面的步骤和SurfaceView的步骤是一致的。如下:
运行之后,发现界面刚显示时,txtInfo文字已经由原来的"Hello world"改为"haha",并且背景色也变了,且新增了一个TextView。而这些操作都是在非UI线程下完成的。
接下来线程sleep 5秒。再执行取消显示ProgressDialog,结果又逆天了,真的顺利取消了,此原因未知,但至少证明了所有的界面刷新并非真的得在UI线程下完成。
然后再次对txtInfo进行更新,结果此次报错了,提示"Only the original thread that created a view hierarchy can touch its views."
Written by Sodino
呵呵,以上的实验也提醒了大家,写代码时一定要考虑周密。另外,对于这种因代码漏洞而引起的特例,知道就好,在正规的代码编程中禁止去使用它。