perf(android): prewarm WebView during idle time to speed up startup

Load WebView native libraries during main thread idle time using
IdleHandler and WebSettings.getDefaultUserAgent(). This reduces
the 200-300ms freeze on first WebView creation.
This commit is contained in:
Johannes Millan 2025-12-31 11:45:52 +01:00
parent 6d82c1982d
commit 25edb4ff1e

View file

@ -1,16 +1,15 @@
package com.superproductivity.superproductivity
import android.app.Application
import android.os.Looper
import android.os.MessageQueue
import android.util.Log
import android.webkit.WebSettings
import com.superproductivity.superproductivity.app.AppLifecycleObserver
import com.superproductivity.superproductivity.app.KeyValStore
class App : Application() {
// NOTE using the web view like this causes all html5 inputs not to work
// val wv: WebView by lazy {
// WebHelper().instanceView(this)
// }
val keyValStore: KeyValStore by lazy {
KeyValStore(this)
}
@ -20,5 +19,36 @@ class App : Application() {
// Initialize AppLifecycleObserver at app startup
AppLifecycleObserver.getInstance()
// Prewarm WebView by loading native libraries during idle time
prewarmWebView()
}
/**
* Prewarms the WebView's Chromium engine by triggering native library loading
* during main thread idle time. This reduces the 200-300ms freeze that occurs
* on first WebView creation.
*
* Uses WebSettings.getDefaultUserAgent() as recommended by the Chromium team -
* it loads WebView libraries without side effects.
*/
private fun prewarmWebView() {
try {
Looper.getMainLooper().queue.addIdleHandler(object : MessageQueue.IdleHandler {
override fun queueIdle(): Boolean {
try {
val startTime = System.currentTimeMillis()
WebSettings.getDefaultUserAgent(this@App)
val duration = System.currentTimeMillis() - startTime
Log.d("SP-WebView", "WebView prewarmed in ${duration}ms")
} catch (e: Exception) {
Log.w("SP-WebView", "WebView prewarm failed: ${e.message}")
}
return false // Remove handler after execution
}
})
} catch (e: Exception) {
Log.w("SP-WebView", "Failed to schedule WebView prewarm: ${e.message}")
}
}
}