WebView обрабатывает веб-контент в отдельном процессе рендеринга. Иногда этот процесс может быть завершен. Это происходит, если система завершает работу процесса рендеринга для освобождения памяти или если сам процесс аварийно завершается. Если вы не обрабатываете такие завершения, ваше приложение также завершит работу.
Почему обработка завершения процесса имеет решающее значение
В более старых версиях Android пользователи реже замечали проблемы, возникающие из-за сбоя обработки завершения процесса рендеринга приложением. Однако в новых версиях Android используются более сложные механизмы управления потреблением ресурсов фоновыми процессами. Следовательно, если ваше приложение не реализует обработчик события onRenderProcessGone , теперь пользователи с большей вероятностью будут наблюдать видимое завершение работы приложений на переднем плане при возвращении в приложение. Реализация API обработки завершения работы необходима для обеспечения корректного восстановления приложения и поддержания стабильного пользовательского опыта.
Используйте API обработки завершения
Вы можете справиться с такими ситуациями, переопределив onRenderProcessGone в вашем WebViewClient .
Ключевые требования для восстановления
Чтобы ваше приложение продолжало работать после завершения процесса рендеринга, каждый WebView в вашем приложении должен соответствовать следующим правилам:
- Не используйте экземпляр WebView повторно. После удаления рендерера этот конкретный объект WebView становится бесполезным. Необходимо удалить объект WebView из иерархии представлений, уничтожить его и очистить все ссылки на него в Activity или Fragment, чтобы избежать случайного продолжения вызова методов уничтоженного экземпляра WebView.
- Создайте новый экземпляр. Если вы хотите продолжить отображение веб-контента, вам потребуется новый экземпляр WebView.
- Возвращает true. Ваша реализация должна возвращать
trueчтобы сообщить коду WebView, что вы обработали ситуацию. Если какой-либоWebViewиспользующий этот процесс рендеринга, не возвращаетtrue, WebView завершит работу вашего приложения или произойдет сбой в соответствии с причиной завершения процесса рендеринга.
Пример реализации
Следующий пример демонстрирует, как обрабатывать подобные завершения в рамках полноценной Activity. Он использует detail.didCrash() для регистрации того, произошёл ли сбой процесса или система завершила рендеринг для освобождения памяти. Независимо от причины, код выполняет очистку, удаляя неработающий WebView из макета, уничтожая его и очищая ссылки Activity, чтобы предотвратить NullPointerException . Затем он подготавливает новый экземпляр и возвращает true , чтобы приложение не закрылось.
Примечание: В следующем примере всегда возвращается true , чтобы приложение продолжало работать. Если вы хотите, чтобы ваше приложение завершало работу при завершении рендеринга WebView, вы можете вернуть false из этого коллбэка. Однако мы рекомендуем обрабатывать повторный запуск и возвращать true для стабильной работы приложения.
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
}
}
Важные соображения
При реализации onRenderProcessGone следует учитывать следующие моменты, чтобы обеспечить стабильность приложения и сохранить прозрачность событий завершения работы:
- Повторные сбои: Если средство рендеринга аварийно завершает работу при загрузке определенной страницы, не следует сразу же перезагружать ту же страницу. Это может привести к повторному сбою нового WebView.
- Видимость: Сбои приложения, вызванные отсутствием этого обработчика, пока не отображаются в отчетах о сбоях Play Console. Хотя будущие обновления могут устранить этот пробел, вам необходимо решить эти проблемы сейчас, чтобы обеспечить стабильность приложения. Внедрение этого обработчика обеспечивает мгновенную видимость причин завершения работы вашего приложения.