【问题标题】:Should the renderingThread of a SurfaceView have the same life-cycle as the view or the activity?SurfaceView 的renderingThread 是否应该与视图或活动具有相同的生命周期?
【发布时间】:2014-02-05 02:42:04
【问题描述】:

创建 SurfaceView 时,通常还会创建一个单独的线程来绘制到表面上。在活动的同时创建和销毁线程是更好的编程实践,还是在表面的同时创建和销毁?

这两种方式都有哪些优点/缺点?

【问题讨论】:

    标签: android design-patterns surfaceview


    【解决方案1】:

    ActivityView 基本上是同时创建的。 Surface 是稍后创建的,这就是 SufaceHolder callbacks 的用途。

    您无法在 Surface 存在之前或被销毁之后对其进行渲染,因此在此之前启动渲染线程或让它继续运行是没有意义的。棘手的部分是回调发生在主 UI 线程上(因为这是您设置它的地方),因此可以在渲染线程工作时调用 surfaceDestroyed() 回调。

    编辑:

    关于 SurfaceView / Activity 生命周期的一些注释包括在下面。这些现在是官方 Android 文档的一部分;请参阅System-Level Graphics 文档中的附录 B。原始帖子可用于历史目的。

    您可以在Grafika 中查看这两种方法的示例。方法一(在 onResume/onPause 中创建/销毁线程)可以在TextureFromCameraActivity 中看到,方法二(在surfaceCreated/surfaceDestroyed 中创建/销毁线程)可以在HardwareScalerActivityRecordFBOActivity 中看到。


    关于应用程序生命周期和SurfaceView 的一些想法。

    有两件有些独立的事情正在发生:

    1. 应用程序 onCreate / onResume / onPause
    2. 表面创建/更改/销毁

    当 Activity 启动时,你会按以下顺序获得回调:

    • onCreate
    • onResume
    • 表面创建
    • surfaceChanged

    如果你点击“返回”,你会得到:

    • 暂停
    • surfaceDestroyed(在 Surface 消失之前调用)

    如果您旋转屏幕,Activity 会被拆除并重新创建,因此您会得到 整个周期。 (您可以通过检查 isFinishing() 来判断这是“快速”重启。)可能可以如此快速地启动/停止活动,以至于 surfaceCreated() 可能会在 onPause() 之后发生,但我'我不确定。

    然而,如果你点击电源按钮来黑屏,你只会得到onPause() -- 没有surfaceDestroyed()Surface 仍然存在,渲染可以继续(你 如果您继续请求它们,甚至会继续获取 Choreographer 事件)。如果你有 锁定屏幕,强制您的Activity 可以被踢出特定的方向,但是 如果没有,您可以使用与以前相同的Surface 退出屏幕空白。

    当使用单独的渲染器线程时,这会引发一个基本问题 SurfaceView:线程的生命周期是否应该与SurfaceActivity?答案是:这取决于你想在屏幕上发生什么 变为空白。有两种基本方法:(1)在Activity上启动/停止线程 开始/停止; (2) 在Surface create/destroy 上启动/停止线程。

    #1 与应用生命周期很好地交互。我们在onResume() 中启动渲染器线程,然后 停止它在onPause()。创建和配置线程时有点尴尬 因为有时 Surface 已经存在,有时则不存在。我们不能简单 将Surface 回调转发给线程,因为如果 Surface 已经存在。所以我们需要查询或缓存Surface状态,并转发 到渲染器线程。注意我们在这里传递对象时要小心一点 线程——最好通过Handler消息传递SurfaceSurfaceHolder,而不是 不仅仅是将其塞入线程中,以避免多核系统上的问题(cf. Android SMP Primer)。

    #2 有一定的吸引力,因为Surface 和渲染器在逻辑上是交织在一起的。 我们在Surface创建后启动线程,避免了线程间 沟通问题。 Surface 创建/更改的消息只是转发。我们 需要确保渲染在屏幕变黑时停止,并在它出现时恢复 非空白;这可能是告诉 Choreographer 停止调用 帧绘制回调。当且仅当我们的onResume() 需要恢复回调 渲染器线程正在运行。但它可能不是那么微不足道——如果我们基于动画 在帧之间经过的时间上,当下一个事件发生时,我们可能会有一个 非常 大的差距 到达,因此可能需要明确的暂停/恢复消息。

    上面主要关心渲染器线程是如何配置的,是否 它正在执行。一个相关的问题是从线程中提取状态,当 Activity 被杀死(在 onPause()onSaveInstanceState() 中)。方法 #1 会奏效 最好的,因为一旦渲染器线程被加入,它的状态就可以 无需同步原语即可访问。

    【讨论】:

    • 我编辑了我的问题,当我指的是表面时,我说过视图。正如您所指出的,视图和活动几乎是同时创建的。
    • 将线程绑定到活动的生命周期的一个优点是,它可以更轻松地保存和恢复线程工作的实例状态。如果线程的生命周期与表面相关联,则无法保证(据我所知)当调用 onSaveInstanceStateonRestoreInstanceState 时线程/表面将有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-08
    • 1970-01-01
    相关资源
    最近更新 更多