«وبنما» محتوای وب خود را در فرایند پردازکننده جداگانهای اجرا میکند. گاهی اوقات، این فرایند ممکن است خاتمه یابد. این اتفاق زمانی میافتد که سیستم ارائهدهنده تصویر را برای بازیابی حافظه متوقف کند یا اگر خود فرایند ازکار بیفتد. اگر این توقفها را مدیریت نکنید، برنامهتان نیز بسته خواهد شد.
چرا رسیدگی به خاتمه فرایند مهم است
در نسخههای قدیمیتر Android، احتمال اینکه کاربران متوجه مشکلی شوند که در آن برنامه نتوانسته است خاتمه فرایند پردازنده را مدیریت کند کمتر بود. بااینحال، نسخههای جدیدتر Android از سازوکارهای پیچیدهتری برای مدیریت مصرف منابع فرایندهای پسزمینهای استفاده میکنند. درنتیجه، اگر برنامهتان کنترلکنندهای برای
onRenderProcessGone پیادهسازی نکند، اکنون احتمال بیشتری وجود دارد که کاربران هنگام بازگشت به برنامه،
توقفهای قابلمشاهده پیشزمینه را مشاهده کنند. پیادهسازی Termination
Handling API برای اطمینان از اینکه برنامهتان بهدرستی بازیابی میشود و تجربه کاربری پایداری را حفظ میکند، الزامی است.
استفاده از Termination Handling API
میتوانید این موقعیتها را با لغو کردن onRenderProcessGone در
WebViewClient مدیریت کنید.
الزامات کلیدی برای بازیابی
برای اینکه برنامهتان پساز پایان فرایند پردازنده گرافیکی همچنان اجرا شود، هر «وبنما» در برنامهتان باید از این قوانین پیروی کند:
- از نمونه WebView مجدداً استفاده نکنید. وقتی موتور پردازکننده ازبین برود، آن شیء «وبنما» خاص بیفایده میشود. باید شیء «وبنما» را از سلسلهمراتب نمای خود بردارید، آن را ازبین ببرید، و هرگونه ارجاع به آن را در «فعالیت» یا «قطعه» خود پاک کنید تا از ادامه تصادفی فراخوانی روشها در نمونه «وبنما» ازبینرفته جلوگیری شود.
- نمونه جدیدی ایجاد کنید. اگر میخواهید نمایش محتوای وب را ادامه دهید، به نمونه «وبنمای» جدیدی نیاز دارید.
- Return true. پیادهسازی شما باید
trueرا برگرداند تا به کد WebView اطلاع دهد که وضعیت را مدیریت کردهاید. اگر هرWebViewکه از آن فرایند پردازنده استفاده میکندtrueرا برنگرداند، «وبنما» برنامهتان را مطابق با دلیل خروج فرایند پردازنده متوقف میکند یا ازکار میاندازد.
نمونه پیادهسازی
مثال زیر نشان میدهد که چگونه این پایانها را در یک
«فعالیت» کامل مدیریت کنید. از detail.didCrash() برای ثبت اینکه آیا فرایند ازکار افتاده است یا اینکه
سیستم ارائهدهنده تصویر را برای بازیابی حافظه متوقف کرده است استفاده میکند. صرفنظر از علت، کد با برداشتن WebView ازکارافتاده از چیدمان، ازبین بردن آن، و پاک کردن ارجاعهای «فعالیت» برای جلوگیری از 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» منعکس نشده است. درحالیکه بهروزرسانیهای آتی ممکن است این شکاف را برطرف کند، باید این مشکلات را اکنون حل کنید تا از پایداری برنامه مطمئن شوید. پیادهسازی این گرداننده باعث میشود فوراً متوجه شوید چرا برنامهتان بسته میشود.
- تشخیص خاتمه پردازنده از مرگ فرایند برنامه:
onRenderProcessGoneموقعیتهایی را که فرایند پردازنده خاتمه مییابد درحالیکه فرایند برنامه شما فعال میماند، مدیریت میکند. اگر کل فرایند برنامه توسط سیستم در پسزمینه متوقف شد، ازonSaveInstanceState()باWebView.saveState()وWebView.restoreState()برای حفظ و بازیابی سابقه پیمایش استفاده کنید. برای مدیریت ایمن وضعیت ذخیرهشده بدون رسیدن به محدودیتهای تراکنش، مدیریت کارآمد وضعیت WebView را ببینید.