現象
WebView 打開頁面,頁面中使用了 Spine web 動畫,當僅僅是加載動畫,執行動畫的初始化過程,持續在頁面等待一段時間,就會導致 APP 閃退。在 OPPO 的部分機型上復現,比如 OPPO R17。
資源加載問題
json 文件 74K,圖片 1M 左右,其他頁面還有更小的圖片。應該不存在資源加載時間過長的問題。
设备兼容性问题
查了一下,webgl 的支持度很廣,WebGL 2.0 chrome 56 就支持了。
版本兼容性問題
Spine player 是遵循 en.esotericsoftware.com/spine-versi… 要求,和 editor 主要版本一致。
至於 Spine player 實現上是否不兼容某些版本的安卓 WebView,就不知道了。
內存不足、內存洩漏
有可能 Spine player 在實例化的過程中,佔用了大量內存。以及沒有正確銷毀實例對象。
期間調試,OPPO R17 WebView 可以打開打包後的頁面,本地開發頁面白屏,應該是不支持 Vite 的開發模式。只能通過本地打包然後 preview 的方式調試,不方便。剛好有 Vivo 手機也會出現問題,於是用 Vivo 手機調試。但是這裡有點問題,也是後面需要注意的一點。OPPO 的表現是頁面會卡一下APP直接閃退;Vivo 的表現大部分是 WebView 卡死,但還能關閉 WebView,APP 中的文字渲染有問題,重新打開WebView頁面,頁面加載異常,有時也是直接導致 APP 閃退。
頁面內存分析
使用 Chrome DevTools
使用 USB 數據線將安卓設備連接到電腦,在設備上打開開發者模式,打開 USB 調試。
在電腦 Chrome 上打開:chrome://inspect,頁面會顯示已連接的設備,在遠程目標下會顯示已打開的頁面,就可以開始調試了。
通過 Memory 面板,可以記錄當前堆內存使用情況。但是使用了下,頁面內存使用也就十幾M ,應該不算多啊。
使用最新版本的 Spine player
官網 demo 復現
<template> <div id="container" class="container"></div></template><script setup>const spine = window.spineonMounted(() => { const player = new spine.SpinePlayer('container', { jsonUrl: 'https://esotericsoftware.com/files/examples/4.2/spineboy/export/spineboy-pro.json', atlasUrl: 'https://esotericsoftware.com/files/examples/4.2/spineboy/export/spineboy-pma.atlas', alpha: true, nimation: 'walk', backgroundColor: '#00000000', showControls: true, }) console.log('player: ', player)})</script>
使用以上 demo 也能在 Vivo 上復現,只是在頁面停留,就會導致卡死。
內存管理優化,確保頁面卸載時,銷毀 Spine 對象和相關資源。
onBeforeUnmount(() => { player?.dispose() player = null spineContainer.value = null})onUnmounted(() => { player?.dispose() player = null spineContainer.value = null})
兼容模式,針對特定機型不應用 Spine 動畫,這種方式處理,簡單粗暴。動畫是次要的,以實現功能為主。畢竟要解決這個問題,需要深入第三方庫實現的原理,其次,還要結合特定 WebView 的分析,這方面我並不擅長。
兼容處理就是通過 userAgent 判斷特定機型是否可以使用 Spine 動畫,具體頁面區分進行處理。
後來測試,通過增加銷毀 Spine 優化後,似乎 OPPO 的問題得到了解決(只是之後看了一下測試環境的頁面,沒有詳細測試),但是 Vivo 的還是不行。我是用 Vivo 進行的調試。