GDa*_*ger 6 android design-patterns surfaceview
在创建SurfaceView时,通常还要创建一个单独的线程来绘制到曲面上.是否更好的编程实践是在活动同时创建和销毁线程,或者同时表面是什么?
这两种方式有哪些优点/缺陷?
fad*_*den 13
将Activity
与View
在基本上相同的时间创建.在Surface
随后建立,而这正是该SufaceHolder回调是.
您无法Surface
在它存在之前或在它被销毁之后进行渲染,因此在此之前启动渲染线程或让它继续运行是没有意义的.棘手的部分是回调发生在主UI线程上(因为那是你设置的地方),因此surfaceDestroyed()
可以在渲染线程正在工作时调用回调.
编辑:
下面列出了有关SurfaceView/Activity生命周期的一些注意事项.这些现在是官方Android文档的一部分; 请参阅系统级图形文档中的附录B. 出于历史目的,下面提供了原始帖子.
您可以在Grafika中看到这两种方法的示例.方法#1(在onResume/onPause中创建/销毁线程)可以在TextureFromCameraActivity中看到,方法#2(在surfaceCreated/surfaceDestroyed中创建/销毁线程)可以在HardwareScalerActivity和RecordFBOActivity中看到.
SurfaceView
.
有两个独立的事情在发生:
当Activity开始时,您将按以下顺序获得回调:
如果你点击"返回",你会得到:
如果旋转屏幕,Activity
则会将其拆除并重新创建,以便获得完整的循环.(您可以通过检查来判断它是"快速"重启isFinishing()
.)可能会很快启动/停止活动,但surfaceCreated()
可能会发生onPause()
,但我不确定.
但是,如果点击电源按钮使屏幕空白,则只能获得onPause()
- 否surfaceDestroyed()
.该Surface
遗骸活着,渲染可以继续(你甚至不断收到编舞的事件,如果你继续要求他们).如果你有一个锁定屏幕强制一个特定的方向你Activity
可以被踢,但如果没有你可以用Surface
你以前的屏幕空白.
当使用单独的渲染器线程时,这会引发一个基本问题
SurfaceView
:是否应该将线程的生命周期Surface
与Activity
?或
?答案是:它取决于屏幕空白时您想要发生什么.有两种基本方法:(1)启动/停止启动/停止线程Activity
; (2)在Surface
create/destroy 上启动/停止线程.
#1与应用程序生命周期很好地交互.我们启动渲染器线程onResume()
并将其停止onPause()
.在创建和配置线程时会有点尴尬,因为有时Surface已经存在,有时它不会存在.我们不能简单地将Surface
回调转发给线程,因为如果Surface
已经存在,它们将不会再次触发
.所以我们需要查询或缓存Surface
状态,并将其转发给渲染器线程.请注意,我们必须在线程之间传递对象时要小心 - 最好传递Surface
或SurfaceHolder
通过Handler
消息,而不是仅仅将其填充到线程中,以避免多核系统出现问题(参见
Android SMP Primer).
#2具有一定的吸引力,因为Surface
和渲染器在逻辑上交织在一起.我们Surface
在创建之后启动线程,这避免了线程间的通信问题. Surface
只需转发创建/更改的消息.我们需要确保在屏幕空白时停止渲染,并在屏幕空白时恢复; 这可能是告诉Choreographer停止调用帧绘制回调的简单问题.onResume()
当且仅当渲染器线程正在运行时,我们才需要恢复回调.它可能不是那么简单 - 如果我们基于帧之间的经过时间进行动画制作,当下一个事件到达时我们可能会有非常大的间隙,因此可能需要明确的暂停/恢复消息.
以上主要涉及渲染器线程的配置方式以及是否正在执行.一个相关的问题是当被杀死时(在或中)从线程中
提取状态.方法#1最适合这种方法,因为一旦渲染了渲染器线程,就可以在没有同步原语的情况下访问它的状态.Activity
onPause()
onSaveInstanceState()
归档时间: |
|
查看次数: |
3304 次 |
最近记录: |