WebView menjalankan konten webnya 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 mengalami error. Jika Anda tidak menangani penghentian ini, aplikasi Anda juga akan keluar.
Alasan pentingnya menangani penghentian proses
Pada versi Android yang lebih rendah, pengguna cenderung tidak menyadari masalah saat
aplikasi gagal menangani penghentian proses perender. Namun, versi Android yang lebih baru menggunakan mekanisme yang lebih kompleks untuk mengelola konsumsi resource proses latar belakang. Oleh karena itu, jika aplikasi Anda tidak menerapkan pengendali untuk
onRenderProcessGone, kemungkinan besar pengguna akan melihat 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 tersebut 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 pemanggilan metode secara tidak sengaja pada instance WebView yang dihancurkan.
- Buat instance baru. Jika ingin terus menampilkan konten web, Anda memerlukan instance WebView baru.
- Menampilkan true. 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 membuat aplikasi Anda error sesuai dengan alasan keluar dari proses perender.
Contoh penerapan
Contoh berikut menunjukkan cara menangani penghentian ini dalam Aktivitas
lengkap. Class ini menggunakan detail.didCrash() untuk mencatat apakah proses error atau apakah
sistem menghentikan perender untuk mengklaim kembali memori. Terlepas dari penyebabnya, kode akan melakukan pembersihan dengan menghapus WebView yang tidak berfungsi dari tata letak, menghancurkannya,
dan menghapus referensi Aktivitas untuk mencegah NullPointerException.
Kemudian, class ini menyiapkan instance baru dan menampilkan true agar 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 tidak adanya callback ini belum tercermin dalam laporan error Konsol Play. Meskipun update mendatang mungkin mengatasi kesenjangan ini, Anda harus menyelesaikan masalah ini sekarang untuk memastikan stabilitas aplikasi. Dengan menerapkan pengendali ini, Anda dapat langsung mengetahui alasan aplikasi Anda keluar.
- Membedakan penghentian perender dari penghentian proses aplikasi:
onRenderProcessGonemenangani situasi saat proses perender dihentikan sementara proses aplikasi Anda tetap aktif. Jika seluruh proses aplikasi dihentikan oleh sistem di latar belakang, gunakanonSaveInstanceState()denganWebView.saveState()danWebView.restoreState()untuk mempertahankan dan memulihkan histori navigasi. Untuk mengelola status tersimpan dengan aman tanpa mencapai batas transaksi, lihat Mengelola status WebView secara efisien.