WebView তার ওয়েব কন্টেন্ট একটি আলাদা রেন্ডারার প্রসেসে চালায়। কখনও কখনও, এই প্রসেসটি বন্ধ হয়ে যেতে পারে। এমনটা ঘটে যখন সিস্টেম মেমরি পুনরুদ্ধারের জন্য রেন্ডারারটিকে বন্ধ করে দেয় অথবা প্রসেসটি নিজেই ক্র্যাশ করে। আপনি যদি এই বন্ধ হয়ে যাওয়াগুলো সামাল না দেন, তাহলে আপনার অ্যাপটিও বন্ধ হয়ে যাবে।
প্রক্রিয়া সমাপ্তি পরিচালনা করা কেন গুরুত্বপূর্ণ
অ্যান্ড্রয়েডের পুরোনো সংস্করণগুলিতে, কোনো অ্যাপ রেন্ডারার প্রসেস টার্মিনেশন পরিচালনা করতে ব্যর্থ হলে ব্যবহারকারীরা সমস্যাটি সহজে লক্ষ্য করতেন না। তবে, অ্যান্ড্রয়েডের নতুন সংস্করণগুলি ব্যাকগ্রাউন্ড প্রসেসের রিসোর্স ব্যবহার পরিচালনা করার জন্য আরও জটিল পদ্ধতি ব্যবহার করে। ফলস্বরূপ, যদি আপনার অ্যাপে onRenderProcessGone এর জন্য কোনো হ্যান্ডলার প্রয়োগ করা না থাকে, তাহলে অ্যাপে ফিরে আসার সময় ব্যবহারকারীরা দৃশ্যমান ফোরগ্রাউন্ড টার্মিনেশন লক্ষ্য করার সম্ভাবনা এখন বেশি। আপনার অ্যাপটি যেন সুষ্ঠুভাবে পুনরুদ্ধার হয় এবং একটি স্থিতিশীল ব্যবহারকারীর অভিজ্ঞতা বজায় রাখে, তা নিশ্চিত করার জন্য টার্মিনেশন হ্যান্ডলিং এপিআই (Termination Handling API) প্রয়োগ করা আবশ্যক।
টার্মিনেশন হ্যান্ডলিং এপিআই ব্যবহার করুন
আপনার WebViewClient এ onRenderProcessGone ওভাররাইড করে আপনি এই পরিস্থিতিগুলো সামাল দিতে পারেন।
পুনরুদ্ধারের জন্য মূল প্রয়োজনীয়তা
একটি রেন্ডারার প্রসেস বন্ধ হয়ে যাওয়ার পরেও আপনার অ্যাপটি চালু রাখতে, আপনার অ্যাপের প্রতিটি WebView-কে অবশ্যই এই নিয়মগুলো অনুসরণ করতে হবে:
- WebView ইনস্ট্যান্সটি পুনরায় ব্যবহার করবেন না। রেন্ডারার চলে গেলে, সেই নির্দিষ্ট WebView অবজেক্টটি অকেজো হয়ে যায়। ভুলবশত ধ্বংসপ্রাপ্ত WebView ইনস্ট্যান্সের মেথড কল করা এড়াতে, আপনাকে অবশ্যই আপনার ভিউ হায়ারার্কি থেকে WebView অবজেক্টটি সরিয়ে ফেলতে হবে, এটিকে ডেস্ট্রয় করতে হবে এবং আপনার Activity বা Fragment থেকে এর সমস্ত রেফারেন্স মুছে ফেলতে হবে।
- একটি নতুন ইনস্ট্যান্স তৈরি করুন। আপনি যদি ওয়েব কন্টেন্ট দেখানো চালিয়ে যেতে চান, তাহলে আপনার একটি নতুন WebView ইনস্ট্যান্স প্রয়োজন।
- ট্রু (true) রিটার্ন করুন। আপনার ইমপ্লিমেন্টেশনকে অবশ্যই
trueরিটার্ন করতে হবে, যাতে WebView কোড বুঝতে পারে যে আপনি পরিস্থিতিটি সামাল দিয়েছেন। যদি সেই রেন্ডারার প্রসেস ব্যবহারকারী কোনোWebViewtrueরিটার্ন না করে, তাহলে WebView রেন্ডারার প্রসেস বন্ধ হওয়ার কারণ অনুযায়ী আপনার অ্যাপটিকে কিল বা ক্র্যাশ করে দেবে।
বাস্তবায়নের উদাহরণ
নিম্নলিখিত উদাহরণটি দেখায় কিভাবে একটি সম্পূর্ণ অ্যাক্টিভিটির মধ্যে এই টার্মিনেশনগুলি পরিচালনা করতে হয়। প্রসেসটি ক্র্যাশ করেছে নাকি সিস্টেম মেমরি পুনরুদ্ধারের জন্য রেন্ডারারকে কিল করেছে, তা লগ করার জন্য এটি 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-টি আবার ক্র্যাশ করতে পারে।
- দৃশ্যমানতা: এই কলব্যাকটি অনুপস্থিত থাকার কারণে অ্যাপ বন্ধ হয়ে গেলে, তা এখনও প্লে কনসোল ক্র্যাশ রিপোর্টে প্রতিফলিত হয় না। যদিও ভবিষ্যতের আপডেটে এই ঘাটতি পূরণ করা হতে পারে, অ্যাপের স্থিতিশীলতা নিশ্চিত করতে আপনাকে এখনই এই সমস্যাগুলো সমাধান করতে হবে। এই হ্যান্ডলারটি প্রয়োগ করলে আপনার অ্যাপ কেন বন্ধ হয়ে যাচ্ছে, তা তাৎক্ষণিকভাবে জানা যায়।