onPause হল একটি Android জীবনচক্র পদ্ধতি যা কল করা হয় যখন একটি Activity ইনপুট ফোকাস হারায় কিন্তু পর্দায় আংশিকভাবে দৃশ্যমান থাকে। সিস্টেম onPause কল করে যখন একটি নতুন Activity অগ্রভাগে আসে, একটি ডায়ালগ খোলে, সাম্প্রতিক অ্যাপস বোতাম টিপা হয়, বা একটি ইনকামিং কল আসে। এই পদ্ধতিটি ব্যবহারকারীর ডেটা সংরক্ষণের শেষ গ্যারান্টিযুক্ত বিন্দু, কারণ onStop এবং onDestroy-এর পরে সিস্টেম অতিরিক্ত কল ছাড়াই প্রক্রিয়া শেষ করতে পারে। onPause-এর ভিতরে, ডেভেলপার খসড়া সংরক্ষণ করে, অ্যানিমেশন বিরতি দেয়, ক্যামেরা মুক্ত করে এবং SharedPreferences-এ বর্তমান UI অবস্থা লেখে. সম্পূর্ণ Activity জীবনচক্র সম্পর্কে আরও জানতে নিবন্ধটি পড়ুন Activity Lifecycle।
মুখ্য বিষয়
onPause হল Activity জীবনচক্রের চতুর্থ পদ্ধতি, যা কল করা হয় যখন পর্দা ইনপুট ফোকাস হারায় কিন্তু ব্যবহারকারীর কাছে আংশিকভাবে দৃশ্যমান থাকে। এটি অ্যাপ সক্রিয়ভাবে চলা এবং লুকানোর মধ্যে একটি «পরিবর্তনকালীন» অবস্থা। সিস্টেম নিম্নলিখিত পরিস্থিতিতে onPause কল করে: অন্য Activity খোলা (একটি নতুন পর্দা বর্তমানটিকে আংশিকভাবে ঢেকে দেয়), একটি ডায়ালগ উইন্ডো দেখা দেওয়া (Dialog, PopupWindow, Snackbar onPause ট্রিগার করে না, কিন্তু DialogFragment করে), সাম্প্রতিক অ্যাপস বোতাম টিপা, ইনকামিং কল, পর্দা লক করার জন্য পাওয়ার বোতাম টিপা।
onPause-এর প্রধান কাজ হল অ্যাপকে লুকানো বা ধ্বংস হওয়ার সম্ভাবনার জন্য প্রস্তুত করা। এটি জীবনচক্রের শেষ বিন্দু যেখানে ডেভেলপার নিশ্চিত হতে পারে যে সিস্টেম অন্য উপাদানে রূপান্তর চালিয়ে যাওয়ার আগে তার কোড কার্যকর হবে। onPause-এর পরে, সিস্টেম onStop কল করে (যদি Activity সম্পূর্ণরূপে লুকানো হয়), তারপরে প্রক্রিয়াটি যেকোনো সময় অতিরিক্ত বিজ্ঞপ্তি ছাড়াই শেষ হতে পারে।
Android Developers (2025) ডকুমেন্টেশন অনুসারে, onPause যতটা সম্ভব হালকা এবং দ্রুত হওয়া উচিত। যতক্ষণ onPause নিয়ন্ত্রণ ফিরিয়ে না দেয়, সিস্টেম পরবর্তী Activity শুরু করতে পারে না — এর মানে ব্যবহারকারী পর্দা রূপান্তরে বিলম্ব দেখেন। Google 100 মিলিসেকেন্ডের কম সময়ে onPause সম্পূর্ণ করার সুপারিশ করে, এবং সমস্ত দীর্ঘ ক্রিয়াকলাপ (ডেটাবেসে সংরক্ষণ, ডিস্কে লেখা) coroutines বা apply()-এর মাধ্যমে অ্যাসিঙ্ক্রোনাসভাবে করা উচিত।
একটি Activity-তে, onPause পদ্ধতি প্রতিবার কল করা হয় যখন পর্দা সক্রিয় থাকা বন্ধ করে কিন্তু আংশিকভাবে প্রদর্শিত হতে পারে। একটি সাধারণ উদাহরণ: ব্যবহারকারী ম্যাপস অ্যাপ খোলে, অবস্থান ভাগ করুন টিপে, এবং ম্যাপসের উপরে একটি সিস্টেম অ্যাপ নির্বাচন ডায়ালগ দেখা যায়। ম্যাপস Activity onPause পায় কিন্তু ডায়ালগের নীচে দৃশ্যমান থাকে। যখন ডায়ালগ বন্ধ হয়, ম্যাপস onResume পায় onStart কল না করেই (পর্দা সম্পূর্ণরূপে লুকানো ছিল না)।
class NoteEditorActivity : AppCompatActivity() {
private var binding: ActivityNoteEditorBinding? = null
private val prefs by lazy {
getSharedPreferences("note_drafts", Context.MODE_PRIVATE)
}
override fun onPause() {
super.onPause()
// নোট খসড়া সংরক্ষণ করুন — অ্যাসিঙ্ক্রোনাসভাবে
prefs.edit()
.putString("draft_title", binding?.titleInput?.text.toString())
.putString("draft_body", binding?.bodyInput?.text.toString())
.putLong("draft_timestamp", System.currentTimeMillis())
.apply()
// ভিডিও বিরতি দিন
binding?.videoPlayer?.pause()
// এক্সক্লুসিভ সম্পদ মুক্ত করুন
releaseCamera()
releaseAudioFocus()
}
override fun onResume() {
super.onResume()
// খসড়া পুনরুদ্ধার করুন
binding?.titleInput?.setText(prefs.getString("draft_title", ""))
binding?.bodyInput?.setText(prefs.getString("draft_body", ""))
acquireCamera()
acquireAudioFocus()
}
}
NoteEditorActivity উদাহরণ onPause-এর সঠিক পরিচালনা প্রদর্শন করে: apply()-এর মাধ্যমে SharedPreferences-এ খসড়া সংরক্ষণ, ভিডিও ফাইল বিরতি দেওয়া, ক্যামেরা এবং অডিও ফোকাস মুক্ত করা। প্রতিটি কল হালকা এবং দ্রুত, ANR ট্রিগার করার জন্য যথেষ্ট সময় UI থ্রেড ব্লক না করে। ক্রম লক্ষ্য করুন: super.onPause() প্রথম লাইনে কল করা হয় — এটি নিশ্চিত করে যে ব্যবহারকারী কোডে ব্যতিক্রম ঘটলেও সিস্টেম লজিক কার্যকর হবে।
অ্যাপ লুকানো বা সিস্টেম দ্বারা বন্ধ করার আগে onPause হল শেষ বিন্দু যেখানে ডেভেলপার নির্ভরযোগ্যভাবে ব্যবহারকারী ডেটা সংরক্ষণ করতে পারে। onStop-এর পরে, সিস্টেম মেমরি কম থাকলে onDestroy কল না করেই প্রক্রিয়া শেষ করতে পারে। onSaveInstanceState() পদ্ধতি onPause-এর পরে কল করা হয়, কিন্তু এর Bundle দীর্ঘমেয়াদী স্টোরেজের জন্য নয় — এটি শুধু পরবর্তী onCreate পর্যন্ত বাঁচে।
অ্যাসিঙ্ক্রোনাস apply()-সহ SharedPreferences হল onPause-এ অল্প পরিমাণ ডেটা সংরক্ষণের সর্বোত্তম উপায় commit()-এর বিপরীতে, যা সিঙ্ক্রোনাসভাবে ডিস্কে ডেটা লেখে এবং বুলিয়ান ফেরত দেয়, apply() তৎক্ষণাৎ মেমরিতে ডেটা সংরক্ষণ করে এবং ডিস্কে অ্যাসিঙ্ক্রোনাস লেখার সময় নির্ধারণ করে। এটি commit()-এর 10–100 মিলিসেকেন্ডের তুলনায় UI থ্রেডে 1 মিলিসেকেন্ডেরও কম সময় নেয়।
override fun onPause() {
super.onPause()
// ❌ খারাপ: সিঙ্ক্রোনাস লেখা থ্রেড ব্লক করে
// prefs.edit().putInt("score", score).commit()
// ✅ ভাল: অ্যাসিঙ্ক্রোনাস লেখা
prefs.edit().putInt("score", score).apply()
// জটিল অবজেক্টের জন্য — ViewModel-এ ক্যাশিং
viewModel.saveState()
}
onPause-এ কাঠামোবদ্ধ ডেটার (Room-এর মাধ্যমে SQLite) জন্য, lifecycleScope-সহ coroutines ব্যবহার করা হয়। ViewModelScope ViewModel ধ্বংস হলে স্বয়ংক্রিয়ভাবে coroutine বাতিল করে, যা বন্ধ ডেটাবেসে লেখা প্রতিরোধ করে। coroutines-সহ Room-এর মাধ্যমে লিখতে 5–15 মিলিসেকেন্ড সময় লাগে এবং UI থ্রেড ব্লক করে না।
// ViewModel-এ:
fun saveDraft(title: String, body: String) {
viewModelScope.launch(Dispatchers.IO) {
noteDao.insert(NoteDraft(title = title, body = body))
}
}
// Activity.onPause-এ:
viewModel.saveDraft(
binding?.titleInput?.text.toString(),
binding?.bodyInput?.text.toString()
)
Fragment-এ onPause কল করা হয় যখন Fragment সক্রিয় থাকা বন্ধ করে কিন্তু দৃশ্যমান থাকতে পারে। এটি ঘটে যখন: FragmentTransaction-এর মাধ্যমে একটি Fragment অন্য Fragment দ্বারা প্রতিস্থাপিত হয়; Fragment ViewPager-এ বর্তমান পৃষ্ঠা না থাকে; Fragment ধারণকারী Activity onPause পায়। Activity onPause এবং Fragment onPause-এর মধ্যে মিথস্ক্রিয়া কঠোরভাবে শ্রেণিবিন্যাসগত: প্রথমে Activity onPause পায়, তারপর তার সমস্ত Fragments।
class MapFragment : Fragment() {
private var mapController: MapController? = null
override fun onPause() {
super.onPause()
mapController?.stopFollowMode()
binding?.mapContainer?.alpha = 0.7f
}
override fun onResume() {
super.onResume()
binding?.mapContainer?.alpha = 1.0f
if (isVisible) {
mapController?.startFollowMode()
}
}
}
onPause-এ মানচিত্র নিয়ে কাজ করার বিশেষত্ব: Google Maps এবং Yandex Maps সক্রিয় ফলো মোডে উল্লেখযোগ্য GPU সম্পদ ব্যবহার করে। ফোকাস হারালে, মানচিত্র অ্যানিমেশন নিষ্ক্রিয় করা এবং মার্কার আপডেট ফ্রিকোয়েন্সি কমানো বোধগম্য, এবং ফোকাস ফিরে পেলে সম্পূর্ণ কার্যকারিতা পুনরুদ্ধার করা উচিত। এটি পর্দার মধ্যে স্যুইচ করার সময় কর্মক্ষমতা উন্নত করে এবং বিদ্যুৎ খরচ হ্রাস করে।
নবীন Android ডেভেলপারদের মধ্যে সবচেয়ে সাধারণ বিভ্রান্তিগুলির মধ্যে একটি হল onPause এবং onStop-এর মধ্যে পার্থক্য না বোঝা। আসুন প্রতিটি পরিস্থিতি পরীক্ষা করি এবং সঠিক পদ্ধতি নির্ধারণ করি।
| পরিস্থিতি | onPause | onStop |
|---|---|---|
| ডায়ালগ উইন্ডো খোলা | কল হয় | কল হয় না |
| নতুন Activity খোলা (অস্বচ্ছ) | কল হয় | কল হয় |
| হোম বোতাম টিপা | কল হয় | কল হয় |
| পর্দা লক | কল হয় | কল হয় |
| ইনকামিং কল | কল হয় | কল হয় |
| স্বচ্ছ Activity উপরে | কল হয় | কল হয় না |
| স্প্লিট স্ক্রিন (অর্ধেক পর্দা) | কল হয় | কল হয় না |
| PiP (পিকচার-ইন-পিকচার) | কল হয় | কল হয় না |
মূল নিয়ম: onPause যেকোনো ফোকাস হারানোর সময় কল হয়, onStop শুধুমাত্র সম্পূর্ণ দৃশ্যমানতা হারানোর সময় কল হয়। যদি Activity দৃশ্যমান থাকে (এমনকি আংশিকভাবে), onStop কল হয় না। এটি স্প্লিট স্ক্রিন, PiP এবং স্বচ্ছ Activity মোডের জন্য গুরুত্বপূর্ণ — এখানে onPause/onResume কাজ করে, কিন্তু onStart/onStop কাজ করে না।
onPause হল সবচেয়ে সময়-গুরুত্বপূর্ণ জীবনচক্র পদ্ধতি কারণ এটি পরবর্তী Activity-এর রেন্ডারিং ব্লক করে। সিস্টেম নতুন Activity দেখানোর আগে বর্তমান Activity-এর onPause সম্পূর্ণ হওয়ার জন্য অপেক্ষা করে। যদি onPause 100 মিলিসেকেন্ডের বেশি সময় নেয়, ব্যবহারকারী রূপান্তরে বিলম্ব লক্ষ্য করে; যদি 5 সেকেন্ডের বেশি সময় নেয়, সিস্টেম ANR দেখায়।
Google Android Performance Guide (2025) onPause-এর জন্য নিম্নলিখিত সুপারিশ দেয়: নেটওয়ার্ক অনুরোধ করবেন না — সেগুলি বাতিল করা উচিত বা WorkManager-এ সরানো উচিত; ডিস্কে বড় ফাইল লিখবেন না — পটভূমি থ্রেডে BufferedWriter ব্যবহার করুন; জটিল SQL কোয়েরি চালাবেন না — Room অপারেশনগুলি coroutines-এর মাধ্যমে অ্যাসিঙ্ক্রোনাস হওয়া উচিত; নতুন অবজেক্ট তৈরি এড়িয়ে চলুন — onPause-তে আবর্জনা সংগ্রহ বিলম্ব বাড়িয়ে তোলে; SharedPreferences-এর জন্য commit()-এর পরিবর্তে apply() ব্যবহার করুন।
override fun onPause() {
super.onPause()
// ❌ খারাপ: HTTP অনুরোধ UI ব্লক করে
// val response = api.syncSave(data).execute()
// ❌ খারাপ: ফাইলে সিঙ্ক্রোনাস লেখা
// FileOutputStream(file).write(data)
// ✅ ভাল: অ্যাসিঙ্ক্রোনাস সংরক্ষণ
lifecycleScope.launch {
withContext(Dispatchers.IO) {
api.saveData(data)
fileDao.write(data)
}
}
// ✅ ভাল: SharedPreferences-এ হালকা লেখা
prefs.edit().putString("key", value).apply()
}
Android Studio Profiler (CPU ট্রেস)-এর মাধ্যমে onPause প্রোফাইলিং সঠিক নির্বাহ সময় দেখায়। যদি onPause 100 ms-এর বেশি সময় নেয়, Profiler পদ্ধতিটি হলুদ রঙে হাইলাইট করে, এবং 500 ms-এর বেশি — লাল রঙে। IT Sectr-এ বাণিজ্যিক প্রকল্পগুলিতে, আমরা Macrobenchmark পরীক্ষা ব্যবহার করি যা স্বয়ংক্রিয়ভাবে Activities-এর মধ্যে রূপান্তর সময় পরীক্ষা করে এবং CI পাইপলাইনে কর্মক্ষমতা হ্রাস সংকেত দেয়।
অভিজ্ঞ ডেভেলপাররাও onPause-এ ভুল করে। আসুন পাঁচটি সাধারণ সমস্যা এবং তাদের সমাধান পরীক্ষা করি।
onPause-এ সিঙ্ক্রোনাস কোয়েরি (.executeAsObservable() coroutines ছাড়া) সহ Room DAO কল করা UI থ্রেডকে 10–50 ms-এর জন্য ব্লক করে। যদি সেই সময়ে GC বা লেখার প্রতিযোগিতা ঘটে, বিলম্ব 200–500 ms-এ পৌঁছাতে পারে। সমাধান: Dispatchers.IO-সহ coroutines বা SharedPreferences-এর জন্য apply() ব্যবহার করুন।
onPause শ্রোতা নিবন্ধনের জায়গা নয়। আপনি যদি onPause-এ BroadcastReceiver নিবন্ধন করেন, তা সক্রিয় থাকবে যখন Activity আর দৃশ্যমান নয়। নিবন্ধন শুধুমাত্র onStart/onResume-এ হওয়া উচিত, এবং onPause/onStop-এ — শুধুমাত্র নিবন্ধন বাতিল। ব্যতিক্রম হল Intent-চালিত API যেগুলির কল করার আগে নিবন্ধন প্রয়োজন।
যদি onPause-এ একটি অপরিচালিত ব্যতিক্রম ঘটে, সিস্টেম onStop এবং onDestroy কল করে না। Activity একটি অনির্ধারিত অবস্থায় আটকে যায়, এবং ফিরে এলে onResume মুক্ত করা সম্পদগুলি সঠিকভাবে পুনরুদ্ধার নাও করতে পারে। সমাধান: Log.e()-এর মাধ্যমে লগিং সহ গুরুত্বপূর্ণ অপারেশনগুলি try/catch-এ মোড়ানো।
onPause-এ সেই ডেটা সংরক্ষণের প্রয়োজন নেই যা সহজেই পুনরুদ্ধার করা যায়। উদাহরণস্বরূপ, API অনুরোধের ফলাফল onPause-এ নয়, বরং প্রাপ্তির সময় Room বা DataStore-এ ক্যাশ করা হয়। শুধুমাত্র যা ব্যবহারকারী ম্যানুয়ালি প্রবেশ করেছে এবং স্বয়ংক্রিয়ভাবে পুনরুদ্ধার করা যায় না তা সংরক্ষণ করুন — ফিল্ডের টেক্সট, নির্বাচিত আইটেম, স্ক্রোল অবস্থান।
super.onPause() কল করা উচিত, কিন্তু onCreate-এর বিপরীতে, এটি বাদ দিলে তাত্ক্ষণিক ক্র্যাশ হয় না। সিস্টেম onPause-এ super-এর অভাব «ক্ষমা» করে, কিন্তু অভ্যন্তরীণ স্টেট মেশিন একটি ভুল অবস্থায় চলে যায়। পরবর্তী onResume কল ইনপুট ফোকাস পুনরুদ্ধারে ব্যর্থ হতে পারে, Activityকে «হিমায়িত» রেখে। সর্বদা super.onPause() যত তাড়াতাড়ি সম্ভব কল করুন।
সচরাচর জিজ্ঞাসা
onPause-এ finish() কল করলে পদ্ধতি থেকে ফিরে আসার সাথে সাথেই Activity শেষ হবে। এটি একটি বৈধ পরিস্থিতি যদি ফোকাস হারানোর সময় পর্দা বন্ধ করার প্রয়োজন হয় (উদাহরণস্বরূপ, অ্যাপ ছোট করার সময় প্রমাণীকরণ পর্দা)। তবে, finish() সম্পূর্ণ সমাপ্তি চক্র শুরু করে: onStop onDestroy, যা রূপান্তরে বিলম্ব যোগ করে। onPause-এ finish() শুধুমাত্র যখন সত্যিই প্রয়োজন তখনই ব্যবহার করুন।
onPause সেই ডেটা সংরক্ষণের জন্য যা প্রক্রিয়া সমাপ্তির পরেও টিকে থাকা উচিত (SharedPreferences/Room-এ খসড়া)। onSaveInstanceState অস্থায়ী UI অবস্থা সংরক্ষণের জন্য যা শুধুমাত্র পরবর্তী onCreate পর্যন্ত প্রয়োজন (স্ক্রোল অবস্থান, নির্বাচিত ট্যাব)। onSaveInstanceState-এর Bundle অ্যাপ সম্পূর্ণরূপে বন্ধ হলে সংরক্ষিত হয় না — এটি কেবল মেমরিতে বিদ্যমান। onPause ডেটা ডিস্কে সংরক্ষিত হয় এবং রিবুটের পরেও টিকে থাকে।
সুপারিশ করা হয় না। onPause-এ ডায়ালগ বা পপআপ খোলার ফলে WindowLeakException হয় যদি Activity ইতিমধ্যেই শেষ হয়ে গেছে। ফোকাস হারানোর সময় বিজ্ঞপ্তি দেখানোর প্রয়োজন হলে, NotificationManager (সিস্টেম বিজ্ঞপ্তি) ব্যবহার করুন — এটি নিরাপদ এবং ব্যবহারকারীর দ্বারা প্রত্যাশিত। বিলম্বিত কর্মের জন্য AlarmManager বা WorkManager ব্যবহার করুন।
Activity সক্রিয় থাকা বন্ধ করার আগে onPause কল করার গ্যারান্টি রয়েছে। সিস্টেম মেমরি মুক্ত করতে প্রক্রিয়া বন্ধ করলে onStop কল নাও হতে পারে — এই ক্ষেত্রে, onDestroy-ও কল হয় না। onPause হল onResume-এর পরে একমাত্র পদ্ধতি যা সর্বদা কল হয়, ফোকাস হারানোর কারণ যাই হোক না কেন। তাই, সমস্ত গুরুত্বপূর্ণ ডেটা ঠিক onPause-এ সংরক্ষিত হয়।
onPause পরীক্ষার জন্য Robolectric বা AndroidX Test-এর FragmentScenario ব্যবহার করা হয়। FragmentScenario.create() moveToState(State.STARTED) moveToState(State.RESUMED) moveToState(State.STARTED) ক্রমিকভাবে onPause কল করে। তারপর যাচাই করা হয় যে ডেটা SharedPreferences-এ সংরক্ষিত হয়েছে বা মক অবজেক্টের মাধ্যমে ক্যামেরা মুক্ত করা হয়েছে। Robolectric 4.12+ শারীরিক ডিভাইস ছাড়াই onPause/onResume অনুকরণ সমর্থন করে।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন