Android - GlSurfaceView во фрагменте запускается дважды одновременно - PullRequest
4 голосов
/ 27 мая 2019

У меня есть приложение для Android, которое использует GlSurfaceView для рендеринга трехмерной полноэкранной сцены внутри фрагмента.Я заметил в профилировщике, что 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 ]

2 голосов
/ 06 июня 2019

Есть несколько вещей, которые вы должны проверить:

  • Вы можете вызывать setRenderer только один раз в жизненном цикле GLSurfaceView.См. GLSurfaceView.setRenderer .
  • Вы вызываете glView.onPause() и glView.onResume(), чтобы остановить рендеринг, если представление находится в фоновом режиме?См. GLSurfaceView жизненный цикл .
  • Вы должны использовать transaction.replace() вместо transaction.add().Вы можете одновременно иметь несколько OpenGlFragments активных
2 голосов
/ 06 июня 2019

Похоже, вы пытаетесь добавить фрагмент вместо замены контейнера.

Вот мой код:

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() также не возвращает ноль, и это гарантировано.

Надеюсь, это поможет !!!

...