【问题标题】:Android - GlSurfaceView in Fragment is running twice at the same timeAndroid - Fragment 中的 GlSurfaceView 同时运行两次
【发布时间】:2019-05-27 19:07:39
【问题描述】:

我有一个 android 应用程序,它使用 GlSurfaceView 在片段内渲染 3D 全屏场景。我在分析器中注意到,GlSurfaceView 实际上正在运行 两次(在两个线程中),占用资源并降低 FPS。我已经通过将相同的 OpenGL 场景(使用相同的 Renderer 实现)渲染到动态壁纸并对其进行分析来确认该问题,它只运行一次。

我在这里做错了吗?


代码如下:

MySurfaceView

class MySurfaceView(ctx: Context): GLSurfaceView(ctx)
{
    init
    {
        setEGLContextClientVersion(3)
        preserveEGLContextOnPause = true
        setRenderer( /* instantiating the renderer class */ )
    }
}

OpenGLFragment

class OpenGLFragment: Fragment()
{
    private lateinit var glView: GLSurfaceView

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View?
    {
        this.glView = MySurfaceView(this.activity)
        return this.glView
    }
}

MainActivity

class MainActivity : FragmentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val fm = supportFragmentManager
        for (i in 0 until fm.getBackStackEntryCount()) {
            fm.popBackStack()
        }

        supportFragmentManager.beginTransaction().add(R.id.main_container, OpenGLFragment())
                    .addToBackStack(null).commit()
    }

}

【问题讨论】:

  • 你确定这行:MySurfaceView(this.activity)。 ,也许是新的 MySurfaceView(this.activity) 。
  • @nikola lukic 这是 kotlin,它没有 new。除了重复片段问题之外,代码还在工作。
  • 你的布局中有什么?一个可能的原因是,如果您的布局文件已经包含 OpenGLFragment,然后您在 onCreate() 中添加了第二个
  • 是不是因为你将Fragment添加到了后台(可能是原因)?只需尝试将Fragment 替换为FragmentManager
  • @JeelVankhede 这到底是怎么工作的?目前,每次我切换到另一个应用程序并返回此应用程序时,它都会重新启动。很好,但是我可以让片段以某种方式在后面运行吗?

标签: android android-layout android-fragments kotlin opengl-es


【解决方案1】:

您似乎正在尝试添加片段而不是替换容器。

这是我的代码:

supportFragmentManager.beginTransaction()
            .replace(R.id.main_container, GLFragment())
            .addToBackStack(null)
            .commit()

片段(使用你的代码不能用this.activity编译)

class GLFragment : Fragment() {

    private lateinit var glView: GLSurfaceView

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        this.glView = MySurfaceView(requireActivity())
        return this.glView
    }
}

GL 视图:

class MySurfaceView constructor(context: Context) : GLSurfaceView(context) {
    init {
        setEGLContextClientVersion(2) // I have used 2 because running on emulator
        preserveEGLContextOnPause = true
        setRenderer(ClearRenderer())
    }
}

internal class ClearRenderer : GLSurfaceView.Renderer {
    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
    }

    override fun onSurfaceChanged(gl: GL10, w: Int, h: Int) {
        gl.glViewport(0, 0, w, h)
    }

    override fun onDrawFrame(gl: GL10) {
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT or GL10.GL_DEPTH_BUFFER_BIT)
    }
}

这是分析器屏幕截图:

所以总结一下,用replace 替换add,用requireActivity() 替换this.activityrequireActivity() 也不会返回 null 并且它是有保证的。

希望对你有帮助!!!

【讨论】:

    【解决方案2】:

    您应该检查几件事:

    • 在 GLSurfaceView 的生命周期中,您只能调用一次setRenderer。见GLSurfaceView.setRenderer
    • 如果视图在后台,您是否正在调用glView.onPause()glView.onResume() 来停止渲染?见GLSurfaceView life-cycle
    • 您应该使用transaction.replace() 而不是transaction.add()。您最终可能会同时激活多个OpenGlFragments

    【讨论】:

    • 谢谢。我想我不使用 onPause 等是当我将应用程序切换到后台然后返回时总是重新创建 OpenGL 状态的原因?我该如何阻止这种情况发生?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-20
    • 1970-01-01
    • 2022-07-14
    • 2014-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多