[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-07-27 (世界標準時間)。"],[],[],null,["# SurfaceView and GLSurfaceView\n\nThe Android app framework UI is based on a hierarchy of objects that start\nwith a [View](https://developer.android.com/reference/android/view/View). All UI elements go through a series of measurements\nand a layout process that fits them into a rectangular area. Then, all visible\nview objects are rendered to a surface that was set up by the\nWindowManager when the app was brought to the foreground. The app's UI thread\nperforms layout and rendering to a buffer per frame.\n\nSurfaceView\n-----------\n\nA SurfaceView is a component that you can use to embed an\nadditional composite layer within your view hierarchy. A SurfaceView takes the\nsame layout parameters as other views, so it can be manipulated like any other\nview, but the SurfaceView's contents are transparent.\n\nWhen you render with an external buffer source, such as GL context or a media\ndecoder, you need to copy buffers from the buffer source to display the buffers\non the screen. Using a SurfaceView enables you to do that.\n\nWhen the SurfaceView's view component is about to become visible, the\nframework asks SurfaceControl to request a new surface from SurfaceFlinger.\nTo receive callbacks when the surface is created or destroyed, use the\n[SurfaceHolder](/docs/core/graphics/arch-sh#surfaceholder) interface. By\ndefault, the newly created surface is placed behind the app UI surface.\nYou can override the default Z-ordering to put the new surface on top.\n\nRendering with SurfaceView is beneficial in cases where you need to render\nto a separate surface, such as when you render with the Camera API or an\nOpenGL ES context. When you render with SurfaceView, SurfaceFlinger directly\ncomposes buffers to the screen. Without a SurfaceView, you need to composite\nbuffers to an offscreen surface, which then gets composited to the screen, so\nrendering with SurfaceView eliminates extra work. After rendering with\nSurfaceView, use the UI thread to coordinate with the activity lifecycle\nand make adjustments to the size or position of the view if needed. Then,\nthe Hardware Composer blends the app UI and the other layers.\n\nThe new surface is the producer side of a BufferQueue, whose consumer is a\nSurfaceFlinger layer. You can update the surface with any mechanism that can\nfeed a BufferQueue, such as surface-supplied Canvas functions, attaching an\nEGLSurface and drawing on the surface with GLES, or configuring a media\ndecoder to write the surface.\n\nSurfaceView and the activity lifecycle\n--------------------------------------\n\nWhen using a SurfaceView, render the surface\nfrom a thread other than the main UI thread.\n\nFor an activity with a SurfaceView, there are two separate but interdependent\nstate machines:\n\n- App `onCreate`/`onResume`/`onPause`\n- Surface created/changed/destroyed\n\nWhen the activity starts, you get callbacks in this order:\n\n1. `onCreate()`\n2. `onResume()`\n3. `surfaceCreated()`\n4. `surfaceChanged()`\n\nIf you click back, you get:\n\n1. `onPause()`\n2. `surfaceDestroyed()` (called just before the surface goes away)\n\nIf you rotate the screen, the activity is torn down and recreated and you\nget the full cycle. You can tell it's a quick restart by checking\n`isFinishing()`. It's possible to start/stop an activity so\nquickly that `surfaceCreated()` happens after\n`onPause()`.\n\nIf you tap the power button to blank the screen, you get only\n`onPause()` without `surfaceDestroyed()`. The surface\nremains active, and rendering can continue. You can keep getting\nChoreographer events if you continue to request them. If you have a lock\nscreen that forces a different orientation, your activity may be restarted when\nthe device is unblanked. Otherwise, you can come out of screen-blank with the\nsame surface as before.\n\nThe lifespan of the thread can be tied to the surface or to the activity,\ndepending on what you want to happen when the screen goes blank. The thread\ncan start/stop either on Activity start/stop or on surface create/destroy.\n\nHaving the thread start/stop on Activity start/stop works well with the app\nlifecycle. You start the renderer thread\nin `onResume()` and stop it in `onStop()`.\nWhen creating and configuring the thread, sometimes the surface\nalready exists, othertimes it doesn't (for example, it's still active after toggling\nthe screen with the power button). You have to wait for the surface to be created\nbefore initializing in the thread. You can't initialize in the\n`surfaceCreate()` callback because it won't fire again if the surface\nwasn't recreated. Instead, query or cache the surface\nstate, and forward it to the renderer thread.\n| **Note:** Be careful when passing objects between threads. It is best to pass the surface or SurfaceHolder through a Handler message (rather than just stuffing it into the thread) to avoid issues on multicore systems. For details, refer to [SMP Primer\n| for Android](http://developer.android.com/training/articles/smp.html).\n\nHaving the thread start/stop on surface create/destroy works well because\nthe surface and the renderer are logically\nintertwined. You start the thread after the surface is created, which\navoids some interthread communication concerns; and surface created/changed\nmessages are simply forwarded. To ensure that rendering stops when the screen\ngoes blank and resumes when it un-blanks, tell Choreographer to stop invoking\nthe frame draw callback. `onResume()` resumes the callbacks if the\nrenderer thread is running. However, if you animate\nbased on elapsed time between frames, there could be a large gap before the\nnext event arrives; using an explicit pause/resume message can solve this issue.\n| **Note:** For an example of having a thread start/stop on surface create/destroy, see [Grafika's Hardware scaler activity](https://github.com/google/grafika/blob/master/app/src/main/java/com/android/grafika/HardwareScalerActivity.java).\n\nBoth options, whether the lifespan of the thread is tied to the Activity\nor the surface, focus on how the renderer thread is\nconfigured and whether it's executing. A related concern is extracting state\nfrom the thread when the activity is killed (in `onStop()` or\n`onSaveInstanceState()`); in such cases, tying the lifespan of the\nthread to the activity works best because\nafter the renderer thread has been joined, the rendered thread's state can be\naccessed without synchronization primitives.\n\nGLSurfaceView\n-------------\n\nThe [GLSurfaceView](https://developer.android.com/reference/android/opengl/GLSurfaceView?hl=en) class provides helper classes for managing EGL contexts,\ninterthread communication, and interaction with the activity lifecycle.\nYou don't need to use a GLSurfaceView to use GLES.\n\nFor example, GLSurfaceView creates a thread for rendering and configures an\nEGL context there. The state is cleaned up automatically when the activity\npauses. Most apps don't need to know anything about EGL to use GLES with\nGLSurfaceView.\n\nIn most cases, GLSurfaceView can make working with GLES\neasier. In some situations, it can get in the way."]]