WebView menjalankan konten web-nya dalam proses perender terpisah. Terkadang, proses ini dapat dihentikan. Hal ini terjadi jika sistem menghentikan perender untuk mengklaim kembali memori atau jika proses itu sendiri error. Jika Anda tidak menangani penghentian ini, aplikasi Anda juga akan keluar.
Alasan pentingnya menangani penghentian proses
Pada Android versi yang lebih rendah, pengguna cenderung tidak menyadari masalah saat aplikasi gagal menangani penghentian proses perender. Namun, Android versi yang lebih baru menggunakan mekanisme yang lebih kompleks untuk mengelola penggunaan resource proses latar belakang. Oleh karena itu, jika aplikasi Anda tidak menerapkan pengendali untuk
onRenderProcessGone, kini kemungkinan besar pengguna akan mengamati penghentian latar depan yang terlihat saat kembali ke aplikasi. Penerapan Termination
Handling API diperlukan untuk memastikan aplikasi Anda pulih dengan baik dan mempertahankan pengalaman pengguna yang stabil.
Menggunakan Termination Handling API
Anda dapat menangani situasi ini dengan mengganti onRenderProcessGone di WebViewClient.
Persyaratan utama untuk pemulihan
Agar aplikasi Anda tetap berjalan setelah proses perender dihentikan, setiap WebView di aplikasi Anda harus mengikuti aturan berikut:
- Jangan gunakan kembali instance WebView. Setelah perender hilang, objek WebView tertentu tidak akan berguna. Anda harus menghapus objek WebView dari hierarki tampilan, menghancurkannya, dan menghapus referensi apa pun ke objek tersebut di Aktivitas atau Fragmen untuk menghindari panggilan metode secara tidak sengaja pada instance WebView yang dihancurkan.
- Buat instance baru. Jika ingin terus menampilkan konten web, Anda memerlukan instance WebView baru.
- Tampilkan nilai benar. Implementasi Anda harus menampilkan
trueuntuk memberi tahu kode WebView bahwa Anda telah menangani situasi tersebut. Jika adaWebViewyang menggunakan proses perender tersebut tidak menampilkantrue, WebView akan menghentikan atau menyebabkan error pada aplikasi Anda sesuai dengan alasan keluar dari proses perender.
Contoh penerapan
Contoh berikut menunjukkan cara menangani penghentian ini dalam Aktivitas lengkap. Contoh ini menggunakan detail.didCrash() untuk mencatat apakah proses error atau apakah sistem menghentikan perender untuk mengklaim kembali memori. Terlepas dari penyebabnya, kode akan dibersihkan dengan menghapus WebView yang tidak aktif dari tata letak, menghancurkannya, dan menghapus referensi Aktivitas untuk mencegah NullPointerException.
Kemudian, kode akan menyiapkan instance baru dan menampilkan true sehingga aplikasi tidak ditutup.
Catatan: Contoh berikut selalu menampilkan true agar aplikasi tetap berjalan.
Jika Anda secara khusus ingin aplikasi dihentikan saat perender WebView dihentikan, Anda dapat menampilkan false dari callback ini. Namun, sebaiknya tangani pembuatan ulang dan tampilkan true untuk pengalaman pengguna yang stabil.
class MyWebViewActivity : AppCompatActivity() {
private var webViewContainer: ViewGroup? = null
private var myWebView: WebView? = null
private var crashCount = 0
private val MAX_CRASHES = 3
// NEW FLAG: Tracks if the WebView crashed while the activity was hidden
private var isWebViewPendingRecovery = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my_web_view)
webViewContainer = findViewById(R.id.my_web_view_container)
initWebView()
}
// NEW LIFECYCLE HOOK: Triggers when the user brings the app back to the foreground
override fun onResume() {
super.onResume()
// If a crash happened in the background, rebuild it now that the user can see it
if (isWebViewPendingRecovery) {
isWebViewPendingRecovery = false
Log.i("MY_APP_TAG", "Activity resumed. Recovering pending WebView now.")
recoverWebView()
}
}
private fun initWebView() {
val webView = WebView(this)
myWebView = webView
webViewContainer?.addView(webView)
webView.webViewClient = object : WebViewClient() {
override fun onRenderProcessGone(view: WebView, detail: RenderProcessGoneDetail): Boolean {
if (detail.didCrash()) {
Log.e("MY_APP_TAG", "The WebView rendering process crashed!")
} else {
Log.e("MY_APP_TAG", "System killed the WebView rendering process to reclaim memory.")
}
// Safely clean up the dead WebView
webViewContainer?.removeView(webView)
webView.destroy()
myWebView = null
// MODIFIED LOGIC: Check the lifecycle state of the Activity
// lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED) means the activity is visible and active
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
Log.i("MY_APP_TAG", "Activity is in foreground. Recovering immediately.")
recoverWebView()
} else {
// The app is in the background. Mark it for later!
Log.w("MY_APP_TAG", "Activity is in background. Postponing recovery until user returns.")
isWebViewPendingRecovery = true
}
return true
}
}
webView.loadUrl("https://www.example.com")
}
// HELPER FUNCTION: Extracted the recovery logic to reuse it
private fun recoverWebView() {
if (crashCount < MAX_CRASHES) {
crashCount++
Log.w("MY_APP_TAG", "Recovering WebView... Attempt $crashCount")
initWebView()
} else {
Log.e("MY_APP_TAG", "WebView crashed too many times. Showing error UI.")
showErrorUI()
}
}
private fun showErrorUI() {
// Example: Inflate an error view
}
override fun onDestroy() {
super.onDestroy()
myWebView?.let {
webViewContainer?.removeView(it)
it.destroy()
}
myWebView = null
}
}
Pertimbangan penting
Saat menerapkan onRenderProcessGone, perhatikan pertimbangan berikut untuk memastikan stabilitas aplikasi dan mempertahankan visibilitas ke peristiwa penghentian:
- Error berulang: Jika perender error saat memuat halaman tertentu, jangan langsung memuat ulang halaman yang sama. Hal ini dapat menyebabkan WebView baru error lagi.
- Visibilitas: Penghentian aplikasi yang disebabkan oleh callback yang tidak ada belum tercermin dalam laporan error Konsol Play. Meskipun update mendatang mungkin mengatasi kesenjangan ini, Anda harus menyelesaikan masalah ini sekarang untuk memastikan stabilitas aplikasi. Penerapan pengendali ini memberikan visibilitas langsung tentang alasan aplikasi Anda keluar.