Android-Fragment中的GlSurfaceView同时运行两次

时间:2019-05-27 19:07:39

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

我有一个使用GlSurfaceView来渲染片段内3D全屏场景的android应用。我在探查器中注意到,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()
    }

}

2 个答案:

答案 0 :(得分:2)

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

这是我的代码:

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
    }
}

GLView:

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)
    }
}

这是探查器的屏幕截图:

enter image description here

因此,为了概括起见,将add替换为replace,将this.activity替换为requireActivity()requireActivity()也不会返回null,这是可以保证的。

希望有帮助!

答案 1 :(得分:2)

您应该检查一些事情:

  • 您只能在GLSurfaceView的生命周期中调用一次setRenderer。参见GLSurfaceView.setRenderer
  • 如果视图位于背景中,您是否正在呼叫glView.onPause()glView.onResume()停止渲染?参见GLSurfaceView life-cycle
  • 您应该使用transaction.replace()而不是transaction.add()。您可能最终同时拥有多个OpenGlFragments