UI 卡頓偵測
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
Android 會從應用程式產生影格並將其顯示在螢幕上以呈現 UI。如果應用程式的 UI 顯示速度緩慢,系統會強制略過影格。發生這種情況時,使用者會看到螢幕畫面不斷閃爍,這稱為「卡頓」。
發生卡頓的原因,通常是 UI 執行緒 (在多數應用程式中為主要執行緒) 的非同步呼叫處理速度減緩或遭到封鎖。您可以透過系統追蹤記錄找出問題。
在 Android 12 以上版本偵測卡頓
對於搭載 Android 12 (API 級別 31) 以上版本的裝置,CPU 分析器的「Display」窗格下方的「Janky frames」軌跡會顯示已擷取的追蹤記錄。
如何偵測卡頓:
在 Android Studio 中,依序選取「View」>「Tool Windows」>「Profiler」,或按一下工具列中的「Profile」
。
如果畫面上顯示「Select Deployment Target」對話方塊,請選擇要部署應用程式的裝置,以便進行剖析。如果您已透過 USB 連線裝置,但清單中未列出該裝置,請確認您已啟用 USB 偵錯。
按一下 CPU 時間軸中任一處,即可開啟 CPU 分析器。
在 CPU 分析器的設定選單中,選取「System Trace」,然後按一下「Record」。與應用程式完成互動後,按一下「Stop」。
「Display」下方應該會顯示「Janky frames」軌跡。根據預設,分析器只會顯示需列為調查的卡頓影格。在每個卡頓的影格中,紅色部分會醒目顯示影格超過轉譯期限的時間區段。
找到某個卡頓影格後,在上面按一下;或者,您也可以按下「M」來調整縮放,將焦點移至所選影格上。這些執行緒中的相關事件會醒目顯示:主執行緒、RenderThread 和 GPU 完成數。
您可以選擇切換「All Frames」和「Lifecycle」核取方塊,分別查看所有影格或轉譯時間的詳細資訊。
在 Android 11 上偵測卡頓
對於使用 Android 11 (API 級別 30) 的裝置,CPU 分析器的「Frame Lifecycle」區段會顯示已擷取的追蹤記錄。

「Frame Lifecycle」區段包含圖層名稱和四個軌跡。每個軌跡都代表影格轉譯管道中的一個階段。「Frame Lifecycle」包含以下元素:
- Frame Lifecycle (Layer name):包含圖層名稱 (位於括弧中) 的區段標題。層級是單一的構成單位。
- Application:此軌跡顯示應用程式將緩衝區移出佇列到重新排入佇列的時段。這通常會對應至
RenderThread
中的追蹤事件。
- Wait for GPU:這個軌跡顯示的是 GPU 擁有緩衝區的時間長度。此為從緩衝區發送到 GPU 至 GPU 完成其在緩衝區工作的時間。但這並不表示 GPU 在這段期間內只會在這個緩衝區中作業。如要進一步瞭解 GPU 在指定時間範圍內的運作方式,建議您使用 Android GPU 檢查器。
- Composition:這個軌跡顯示的是從 SurfaceFlinger 將緩衝區鎖存並傳送以供系統組合開始,到將緩衝區傳送至螢幕畫面的時間。
- Frames on Display:這個軌跡顯示了影格停留在畫面上的時間長度。
Frame Lifecycle:這個區段說明了影格緩衝區在算繪管道的不同階段間的移動方式。影格會依影格編號進行顏色編碼,方便您更容易追蹤特定的影格。
Android Studio 也會在「All Frames」分頁中以表格格式顯示追蹤記錄中的所有影格。

「Frame #」、「Application」、「Wait for GPU」和「Composition」資料欄代表的資料與「Frame Lifecycle」區段內的軌跡資料相同。「Frame Duration」資料欄代表從「Application」開始到「Frames on Display」開始的時間。這本質上是端到端顯示影格所需的時間。
您可以按照任何資料欄排序影格表格,以快速找到最短或最長的影格。表格也支援分頁控制選項,可協助您瀏覽數百個影格。
如要在 Android 11 上偵測及調查卡頓,請按照下列步驟操作:
按照「Application」欄對「All Frames」表格進行遞減排序,將最耗時的影格優先顯示。

查看最長的執行時間,然後選取表格列。這會在左側時間軸檢視畫面中放大所選影格。

在「Frame Lifecycle」和「Threads」區段中尋找相關的執行緒。

在 Android 10 以下版本偵測卡頓
對於搭載 Android 10 (API 級別 29) 以下版本的裝置,相關的 OS 圖形管道資訊會顯示在 CPU 分析器系統追蹤記錄的單一區段內,該部分稱為「Display」。

- 影格:本節顯示應用程式中的 UI 執行緒和
RenderThread
追蹤記錄事件。超過 16 毫秒的事件會呈紅色,以醒目顯示潛在卡頓影格,因為其已超過顯示 60 個每秒影格數 (fps) 的期限。
- SurfaceFlinger:這個區段顯示的是 SurfaceFlinger 處理畫格緩衝區的時間。SurfaceFlinger 是一種系統處理程序,用來傳送要顯示的緩衝。
- 「VSYNC」:本節顯示 VSYNC,這是同步處理顯示管道的信號。這個軌跡會顯示 VSYNC-app 信號,在應用程式啟動太晚時顯示。原因通常是因為 UI 執行緒處於忙碌狀態。當您使用動畫功能時,螢幕會有可見的閃爍畫面,並在動畫或捲動完成前加上額外輸入延遲時間。由於顯示頻率可能會超過每秒 60 次,或以可變速率顯示,因此這對於查看高刷新率的螢幕尤其重要。
- BufferQueue:這個部分顯示有多少影格已排入緩衝區,正在等待 SurfaceFlinger 使用。如果應用程式已部署至搭載 Android 9 (API 級別 28) 以上版本的裝置,這個測試群組會顯示應用程式途徑 BufferQueue (
0
、1
或 2
) 的緩衝區數量。BufferQueue 可協助您瞭解圖片緩衝區在 Android 圖形元件間移動時的狀態。例如,2
表示應用程式目前處於三重緩衝處理,造成額外的輸入延遲時間。
「Display」部分會提供實用的信號來偵測潛在的卡頓情形,例如 UI 執行緒或 RenderThread
耗時超過 16 ms 時。如要調查導致卡頓的具體詳細資料,可以查看「Threads」區段,其中顯示與 UI 算繪作業相關的執行緒。

上圖中,「Threads」區段顯示了 UI 執行緒 (java.com.google.samples.apps.iosched
)、RenderThread
和 GPU completion
執行緒。這些是與 UI 顯示相關的執行緒,可能會導致卡頓。
如要在 Android 10 以下版本中偵測卡頓,請按照下列步驟操作:
查看「Display」中的「Frames」軌跡。紅框是調查的候選項。

找到可能卡頓的影格時,請按下 W
鍵,或按住 Control 鍵 (macOS 為 Command 鍵) 並捲動滑鼠滾輪來放大畫面。繼續放大,直到開始在 UI 執行緒和 RenderThread
中看到追蹤事件為止。

在上圖中,UI 執行緒呼叫 Choreographer
以協調動畫、檢視版面配置、圖片繪圖及相關程序時,會顯示 Choreographer#doFrame
。RenderThread
組成並發出對 GPU 的實際繪圖指令時,會顯示 DrawFrames
。
如果您看到特別長的追蹤記錄事件,可以進一步縮小,找出導致顯示速度變慢的原因。上圖顯示了 UI 執行緒中的 inflate
,這表示應用程式正在耗時加載版面配置。當您放大其中一個 inflate
事件時,您可準確瞭解每個 UI 元件花費的時間,如下圖所示。

瞭解詳情
如要進一步瞭解如何減少卡頓,請參閱「卡頓的常見來源」。
這個頁面中的內容和程式碼範例均受《內容授權》中的授權所規範。Java 與 OpenJDK 是 Oracle 和/或其關係企業的商標或註冊商標。
上次更新時間:2025-07-27 (世界標準時間)。
[[["容易理解","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,["# UI jank detection\n\nAndroid renders UI by generating a frame from your app and displaying it on\nthe screen. If your app suffers from slow UI rendering, then the system is\nforced to skip frames. When this happens, the user perceives a recurring flicker\non their screen, which is referred to as *jank*.\n\nWhen jank occurs, it's usually because of some deceleration or blocking async\ncall on the UI thread (in most apps, it's the main thread). You can use system\ntraces to identify where the problem is.\n\nDetect jank on Android 12 and higher\n------------------------------------\n\nFor devices using Android 12 (API level 31) or higher, a captured trace is shown\nin the **Janky frames** track under the **Display** pane in the CPU Profiler.\n\nTo detect jank,\n\n1. In Android Studio, select **View \\\u003e Tool Windows \\\u003e Profiler** or click **Profile**\n in the toolbar.\n\n If prompted by the **Select Deployment Target** dialog, choose the device to\n which to deploy your app for profiling. If you've connected a device over USB\n but don't see it listed, ensure that you have\n [enabled USB debugging](/studio/debug/dev-options#enable).\n2. Click anywhere in the **CPU** timeline to open the CPU Profiler.\n\n3. Select **System Trace** from the configurations menu in the CPU Profiler and\n click **Record** . After you finish interacting with your app, click **Stop**.\n\n4. You should see the **Janky frames** track under **Display** . By default, the\n Profiler only shows janky frames as candidates for investigation. Within each\n janky frame, the red portion highlights the duration the frame takes past its\n rendering deadline.\n\n5. Once you find a janky frame, click on it; optionally, you can press **M** to\n adjust the zoom to focus on the selected frame. The relevant events are\n highlighted in these threads: the main thread, **RenderThread** and\n **GPU completion** .\n\n6. You can optionally see all frames or a breakdown of the rendering time by\n toggling the checkboxes **All Frames** and **Lifecycle** , respectively.\n\nDetect jank on Android 11\n-------------------------\n\nFor devices using Android 11 (API level 30), a captured trace is shown in the\n**Frame Lifecycle** section in the CPU Profiler.\n\nThe **Frame Lifecycle** section contains the layer name and four tracks. Each\ntrack represents one stage in the frame rendering pipeline. The **Frame\nLifecycle** elements are as follows:\n\n1. **Frame Lifecycle (Layer name)** : The section title contains the layer name in parentheses. A *layer* is a single unit of composition.\n2. **Application** : This track shows the time from when the buffer was dequeued by the app to when it was enqueued back. This usually corresponds to the trace events in `RenderThread`.\n3. **Wait for GPU** : This track shows how long the buffer was owned by the GPU. This is the time from when the buffer is sent to the GPU to when the GPU finishes its work on the buffer. **This does not indicate that the GPU was working only on\n this buffer during this time.** For detailed info on what the GPU works on during a given time, you may want to use [Android GPU Inspector](/agi).\n4. **Composition**: This track shows the time starting from when SurfaceFlinger latches on to the buffer and sends it for composition, to when the buffer is sent to the display.\n5. **Frames on display**: This track shows how long the frame was on the screen.\n\nThe **Frame Lifecycle** section illustrates how a frame buffer moves between\ndifferent stages of the rendering pipeline. The frames are color coded by frame\nnumber so that it's easier to track a particular frame.\n\nAndroid Studio also shows all frames in the trace in a table format in the **All\nFrames** tab.\n\nThe **Frame #** , **Application** , **Wait for GPU** , and\n**Composition** columns represent the same data as the tracks in the **Frame\nLifecycle** section as above. The column **Frame Duration** represents the time\nfrom the start of **Application** to the start of **Frames on Display**. This is\nessentially how long it takes to render a frame end-to-end.\n\nYou can sort the frames table by any column to quickly find the shortest or\nlongest frame. The table also supports pagination controls that help you navigate\nthrough hundreds of frames.\n\nTo detect and investigate jank on Android 11, follow these steps:\n\n1. Sort the **All Frames** table by the **Application** column in descending\n order, so that the frames that take the longest appear first.\n\n2. Find the longest running frames and select the table row. This zooms in on\n the selected frame in the timeline view to the left.\n\n3. Look for relevant threads in the **Frame Lifecycle** and **Threads** sections.\n\nDetect jank on Android 10 and lower\n-----------------------------------\n\nFor devices using Android 10 (API level 29) and lower, relevant OS graphics\npipeline information is displayed in a single section on the CPU Profiler system\ntrace called **Display**.\n\n- **Frames** : This section shows the UI thread and `RenderThread` trace events in your app. Events that are longer than 16ms are colored red to highlight potential janky frames because they exceed the deadline to render at 60 frames per second (fps).\n- **SurfaceFlinger**: This section shows when the SurfaceFlinger processes the frame buffers. SurfaceFlinger is a system process that is responsible for sending buffers to display.\n- **VSYNC**: This section displays the VSYNC, a signal that synchronizes the display pipeline. The track displays the VSYNC-app signal, which shows when your app is starting too late. Typically, this occurs because the UI thread is busy. It causes a visible flicker to appear on your screen during an animation and adds extra input latency until the animation or scroll completes. This is especially important to view for high-refresh-rate displays, as they may occur more frequently than 60 times per second or at a variable rate.\n- **BufferQueue** : This section shows how many frame buffers are queued up and are waiting for SurfaceFlinger to consume. For apps deployed to devices running Android 9 (API level 28) or higher, this track shows the buffer count of the app's surface [BufferQueue](https://source.android.com/devices/graphics#bufferqueue) (`0`, `1`, or `2`). BufferQueue can help you understand the state of image buffers as they move between the Android graphics components. For example, a value of `2` means that the app is currently triple-buffered, which results in extra input latency.\n\nThe **Display** section provides useful signals to detect potential jank---for\nexample, when the UI thread or `RenderThread` takes longer than 16 ms. To investigate\nexact details of what caused the jank, you can probe the **Threads**\nsection, which shows the threads relevant to UI rendering.\n\nIn the figure above, the **Threads** section shows the UI thread\n(`java.com.google.samples.apps.iosched`), `RenderThread`, and the `GPU completion`\nthread. These are the threads relevant to UI rendering and may contribute to\njank.\n\nTo detect jank on Android 10 or lower, follow these steps:\n\n1. Look at the **Frames** track in **Display**. The red frames are candidates\n for investigation.\n\n2. Once you find a potentially janky frame, zoom in by pressing `W` or\n scrolling the mouse wheel while holding \u003ckbd\u003eControl\u003c/kbd\u003e\n (\u003ckbd\u003eCommand\u003c/kbd\u003e on macOS). Continue zooming in until you start to see the\n trace events in the UI thread and `RenderThread`.\n\n In the figure above, `Choreographer#doFrame` shows when the UI thread calls\n [`Choreographer`](/reference/android/view/Choreographer) to coordinate\n animation, view layout, image drawing, and related processes. `DrawFrames`\n shows when `RenderThread` forms and issues actual drawing commands to the GPU.\n3. If you see a particularly long trace event, you can zoom in further and find out\n what may have contributed to the slow rendering. The figure above shows `inflate`\n in the UI thread, which means the app is spending time on inflating the layout.\n When you zoom into one of the `inflate` events, you can find out exactly how long\n each UI component is taking, as shown below.\n\nLearn more\n----------\n\nTo learn more about how to reduce jank, see\n[Common sources of jank](/topic/performance/vitals/render#common-jank)."]]