Android:使用 SurfaceView 重新获得焦点

Posted

技术标签:

【中文标题】Android:使用 SurfaceView 重新获得焦点【英文标题】:Android: Regaining focus using SurfaceView 【发布时间】:2010-10-14 21:54:25 【问题描述】:

我目前正在熟悉 android,正在使用 Lunar Lander 示例。

我发现,如果您离开应用程序(例如,点击通话按钮),它将破坏底层表面(调用 surfaceDestroyed)。

向后导航(这将触发onWindowVisibilityChanged)应用程序将崩溃,因为它会尝试在不重新创建的情况下绘制到表面。

我可以在onWindowVisibilityChanged(或其他任何地方)中添加一些代码来重新生成 SurfaceView 的底层表面并很好地恢复执行吗?

感觉这应该是一个简单的函数调用,但我在 API 文档中找不到任何内容。

谢谢!

【问题讨论】:

【参考方案1】:

“mSurfaceExists = true”的这个解决方案对我也不起作用。看起来 surfaceCreated() 没有被调用,因为 super.onWindowVisibilityChanged() 没有被调用。所以没有创建表面并且它不会崩溃,因为 threas.start 没有被调用。

我认为问题是: 调用 thread.start() 会导致错误,因为线程已经启动。 但是在surfaceDestroyed() 中,thread.join 导致线程完成并死亡。并且线程一旦死了就无法重启。

我猜诀窍是在surfacecreated 中创建一个新线程,或者仅在用户调用应用程序完成(返回键)而不是暂停(home 键)时才导致线程完成。这可以通过在活动上调用 isFinishing() 来检查。

不确定这是否可行。我很快就会尝试这个。

【讨论】:

刚刚测试过(调试过),正如你所想的那样。只要应用程序被隐藏并且线程停止,surfaceDestroyed() 就会被调用。再次显示应用程序时,surfaceCreated() 被调用并尝试再次启动线程,这导致IllegalThreadStateException【参考方案2】:

误诊!应用程序会自动重新创建表面,但其中有一个调用会在创建之前尝试对其进行绘制。

解决问题:

boolean mSurfaceExists;
...
public void surfaceDestroyed(SurfaceHolder holder) 
    mSurfaceExists = false;
    ...


public void surfaceCreated(SurfaceHolder holder) 
    mSurfaceExists = true;
    ...


protected void onWindowVisibilityChanged(int visibility) 
    // only call base if there's a surface
    if(mSurfaceExists)
        super.onWindowVisibilityChanged(visibility);

现在一切都好起来了。 (据我所知,无论如何,如果这是不好的做法,Java/Android 专家可以随时发表评论!)

【讨论】:

我试过这个,但它没有正确绘制月球着陆器游戏。你得到的只是文字而不是宇宙飞船或背景。

以上是关于Android:使用 SurfaceView 重新获得焦点的主要内容,如果未能解决你的问题,请参考以下文章

Android--SurfaceView使用详解

android-tip-关于SurfaceView的使用

android surfaceview 怎么用

Android使用SurfaceView搭建OpenGL环境

Android使用SurfaceView搭建OpenGL环境

Android使用SurfaceView搭建OpenGL环境