onStart হল একটি Android জীবনচক্র পদ্ধতি যা কল করা হয় যখন একটি Activity বা Fragment ব্যবহারকারীর কাছে দৃশ্যমান হয়। এই মুহুর্তে, স্ক্রিনটি ডিভাইস ডিসপ্লেতে উপস্থিত হয়, কিন্তু এখনও ব্যবহারকারীর সাথে যোগাযোগ করতে পারে না — onResume কল না হওয়া পর্যন্ত ইনপুট ফোকাস অনুপস্থিত থাকে। onStart পদ্ধতি সিস্টেম লিসেনার নিবন্ধন, জিওলোকেশন সার্ভিসের সাথে সংযোগ এবং অ্যানিমেশন চালু করার জন্য আদর্শ যা কম্পোনেন্ট স্ক্রিনে দৃশ্যমান থাকা পর্যন্ত চলা উচিত। সম্পূর্ণ Activity জীবনচক্র সম্পর্কে আরও জানতে নিবন্ধটি পড়ুন Activity Lifecycle।
মুখ্য বিষয়
onStart হল Activity জীবনচক্রের দ্বিতীয় পদ্ধতি, যা সিস্টেম দ্বারা onCreate এর পরে (অথবা বন্ধ অবস্থা থেকে ফিরে আসার সময় onRestart এর পরে) কল করা হয়। onStart কলের মুহুর্তে, Activity বা Fragment স্ক্রিনে দৃশ্যমান হয়। ব্যবহারকারী ইন্টারফেস দেখেন, কিন্তু স্ক্রিন এখনও মিথস্ক্রিয়ার জন্য প্রস্তুত নয় — ইনপুট ফোকাস শুধুমাত্র onResume এর পরে উপস্থিত হবে।
onStart পদ্ধতি Activity এর «দৃশ্যমান জীবনকাল» (visible lifetime) এর অংশ — onStart এবং onStop এর মধ্যে ব্যবধান। এই সময়ের মধ্যে, Activity অন্যান্য উইন্ডো (যেমন স্বচ্ছ Activity বা ডায়ালগ উইন্ডো) দ্বারা আংশিকভাবে ঢাকা থাকতে পারে, কিন্তু এর UI দৃশ্যমান থাকে। এটি দৃশ্যমান জীবনকালকে «অগ্রভূমি জীবনকাল» (onResume — onPause) থেকে আলাদা করে, যখন Activity এর পূর্ণ ইনপুট ফোকাস থাকে।
এই তিন-স্তরের শ্রেণিবিন্যাস বোঝা কোডের সঠিক বিতরণের জন্য গুরুত্বপূর্ণ। onCreate — এককালীন আরম্ভ, onStart — দৃশ্যমান সম্পদ সংযুক্ত করা, onResume — একচেটিয়া সম্পদে এক্সক্লুসিভ অ্যাক্সেস। ডেভেলপার যিনি এই স্তরগুলিকে বিভ্রান্ত করেন, তিনি স্ক্রিনের মধ্যে স্যুইচ করার সময় মেমরি লিক বা অ্যাপ্লিকেশনের ভুল আচরণের ঝুঁকি নেন।
Activity তে, onStart পদ্ধতি প্রতিবার কল করা হয় যখন স্ক্রিন ডিসপ্লেতে উপস্থিত হয় — প্রথম লঞ্চে (onCreate এর পরে) এবং পটভূমি থেকে ফিরে আসার সময় (onRestart এর পরে) উভয় ক্ষেত্রেই। onCreate এর বিপরীতে, onStart একটি Activity ইনস্ট্যান্সের জীবনে একাধিকবার কল করা যেতে পারে, তাই এখানে সেই কোড রাখা হয় যা স্ক্রিন উপস্থিত হলে প্রতিবার কার্যকর করা উচিত।
class DashboardActivity : AppCompatActivity() {
private val connectivityReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val isConnected = ... // ConnectivityManager পরীক্ষা
binding?.statusIndicator?.setColor(
if (isConnected) Color.GREEN else Color.RED
)
}
}
override fun onStart() {
super.onStart()
registerReceiver(
connectivityReceiver,
IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
)
SensorManager.getInstance().registerStepCounter()
}
override fun onStop() {
unregisterReceiver(connectivityReceiver)
SensorManager.getInstance().unregisterStepCounter()
super.onStop()
}
}
মূল নিয়ম: onStart এ সংযুক্ত সমস্ত সম্পদ onStop এ মুক্ত করতে হবে। এটি নিশ্চিত করে যে যখন Activity স্ক্রিন থেকে লুকানো থাকে, তখন এটি ব্যাটারি খরচ করে না, সিস্টেম ইভেন্ট শোনে না এবং মেমরি দখল করে না। Android Studio তে lint নিয়ম রয়েছে যা সংশ্লিষ্ট অপসারণ ছাড়াই BroadcastReceiver নিবন্ধন করার বিষয়ে সতর্ক করে।
Fragment এ onStart কন্টেইনার Activity এর জীবনচক্রের সাথে ঘনিষ্ঠভাবে যুক্ত। Fragment onStart কল পায় যখন এর ধারণকারী Activity onStart পেয়েছে। তবে, যদি Fragment বিলম্বিত মোডে যোগ করা হয় (FragmentTransaction.commit() addToBackStack ছাড়া), তাহলে onStart বিলম্বের সাথে কল হতে পারে।
class MapFragment : Fragment() {
private var mapView: MapView? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
mapView = MapView(requireContext())
return mapView!!
}
override fun onStart() {
super.onStart()
mapView?.onStart()
LocationService.connect(requireContext())
}
override fun onStop() {
mapView?.onStop()
LocationService.disconnect()
super.onStop()
}
}
Fragment.onStart এর বিশেষত্ব: যদি Fragment offscreenPageLimit = 1 সহ ViewPager এ থাকে, তাহলে প্রতিবেশী ফ্রাগমেন্টগুলিও দৃশ্যমান হওয়ার আগে onStart পাবে। এটি অকাল লিসেনার নিবন্ধনের কারণ হতে পারে। এই ধরনের ক্ষেত্রে, setUserVisibleHint() পদ্ধতি ব্যবহার করুন বা শুধুমাত্র প্রকৃতপক্ষে দৃশ্যমান ফ্রাগমেন্টের জন্য লিসেনার নিবন্ধন করতে onStart এর ভিতরে isVisible পরীক্ষা করুন।
onStart এবং onResume এর মধ্যে প্রধান পার্থক্য হল স্ক্রিন কার্যকলাপের স্তর। onStart ইঙ্গিত দেয় যে Activity স্ক্রিনে দৃশ্যমান কিন্তু প্রয়োজনীয়ভাবে অগ্রভাগে নয়। onResume ইঙ্গিত দেয় যে Activity অগ্রভাগে রয়েছে এবং এর ইনপুট ফোকাস রয়েছে। পার্থক্যটি একটি ডায়ালগ উইন্ডো উদাহরণ দ্বারা প্রদর্শিত হয়: যখন Activity এর উপরে Dialog উপস্থিত হয়, Activity onResume হারায় (onPause কল হয়) কিন্তু দৃশ্যমান থাকে — onStart/onStop কল হয় না।
তুলনা সারণী স্পষ্টভাবে দেখায় কোন পরিস্থিতিতে প্রতিটি পদ্ধতি কল করা হয়:
| পরিস্থিতি | onStart | onResume |
|---|---|---|
| অ্যাপ্লিকেশন লঞ্চ | কল হয় | কল হয় |
| Activity এর উপরে Dialog খোলা | কল হয় না | onPause (ফোকাস হারায়) |
| হোম বাটন চাপা | onStop (লুকানো) | onPause → onStop |
| সাম্প্রতিক থেকে ফিরে আসা | onStart (দৃশ্যমান) | onResume (ফোকাস) |
| স্ক্রিন ঘোরানো | onCreate → onStart | → onResume |
| ইনকামিং কল | onStop (লুকানো) | onPause → onStop |
এই সারণী ডেভেলপারকে নির্দিষ্ট কোড কোন পদ্ধতিতে রাখতে হবে তা সিদ্ধান্ত নিতে সাহায্য করে। উদাহরণস্বরূপ, যদি অ্যাপ্লিকেশনটির যেকোনো স্ক্রিন ওভারল্যাপে (এমনকি ডায়ালগ) ভিডিও প্লেব্যাক বিরাম দেওয়া উচিত, তাহলে কোড onPause এ রাখা হয়। যদি ভিডিও শুধুমাত্র স্ক্রিন সম্পূর্ণ লুকানো হলে বন্ধ হওয়া উচিত — কোড onStop এ রাখা হয়।
onStart হল সেই লিসেনারগুলি নিবন্ধনের জন্য সর্বোত্তম স্থান যা শুধুমাত্র তখন কাজ করা উচিত যখন Activity স্ক্রিনে দৃশ্যমান হয়। এটি তিনটি প্রধান ধরনের সিস্টেম কম্পোনেন্টের সাথে সম্পর্কিত: সিস্টেম ইভেন্টের জন্য BroadcastReceiver, জিওলোকেশনের জন্য LocationListener এবং ডিভাইস সেন্সরের জন্য SensorListener।
BroadcastReceiver onStart এ Context.registerReceiver() এর মাধ্যমে গতিশীলভাবে নিবন্ধিত হয় এবং onStop এ unregisterReceiver() এর মাধ্যমে অপসারণ করা হয়। গতিশীল নিবন্ধন স্থির নিবন্ধন (ম্যানিফেস্টে) থেকে উত্তম কারণ এটি রিসিভারের জীবনকালকে Activity এর দৃশ্যমান সময়ের মধ্যে সীমাবদ্ধ করে — Activity লুকানো থাকলে অ্যাপ্লিকেশন সিস্টেম ব্রডকাস্ট বার্তা থেকে জেগে ওঠে না।
private val batteryReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
binding?.batteryText?.text = "$level%"
}
}
override fun onStart() {
super.onStart()
registerReceiver(batteryReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
}
override fun onStop() {
unregisterReceiver(batteryReceiver)
super.onStop()
}
জিওলোকেশন এবং সেন্সর সম্পদ-নিবিড় অপারেশন। onStart এ GPS আপডেটের অনুরোধ করা এবং onStop এ বাতিল করা নিশ্চিত করে যে স্ক্রিন লুকানো থাকলে অ্যাপ্লিকেশন ব্যাটারি শেষ করে না। সূক্ষ্ম টিউনিংয়ের জন্য, ন্যূনতম ব্যবধান এবং দূরত্ব সহ requestLocationUpdates ব্যবহার করুন — উদাহরণস্বরূপ, 10 সেকেন্ড এবং 10 মিটার, যা নির্ভুলতা এবং শক্তি খরচের মধ্যে সর্বোত্তম ভারসাম্য দেয়।
onCreate এর পরিবর্তে onStart এ অ্যানিমেশন শুরু করা নিশ্চিত করে যে অ্যানিমেশন প্রতিবার স্ক্রিন উপস্থিত হলে শুরু হয়। আপনি যদি onCreate এ অ্যানিমেশন শুরু করেন, তবে এটি শুধুমাত্র প্রথম Activity তৈরিতে কাজ করবে, পটভূমি থেকে ফিরে আসার সময় নয়। onStart প্রতিবার কল হয় যখন Activity দৃশ্যমান হয়, যা এটিকে চক্রীয় অ্যানিমেশন এবং রূপান্তর শুরু করার জন্য আদর্শ স্থান করে তোলে।
private lateinit var pulseAnimator: ValueAnimator
override fun onStart() {
super.onStart()
pulseAnimator.start()
binding?.loadingIndicator?.animate()?.alpha(1f)?.start()
}
override fun onStop() {
pulseAnimator.cancel()
binding?.loadingIndicator?.animate()?.cancel()
super.onStop()
}
ObjectAnimator বা ValueAnimator ব্যবহার করে অ্যানিমেশনের জন্য, onStop এ cancel() কল করা গুরুত্বপূর্ণ। যদি Activity লুকানোর পরে অ্যানিমেশন চলতে থাকে, তবে এটি অকারণে GPU এবং CPU সম্পদ খরচ করে, ডিভাইসের কর্মক্ষমতা হ্রাস করে এবং ব্যাটারি শেষ হওয়ার গতি বাড়ায়। Android Studio Profiler (GPU গ্রাফ) আপনাকে সক্রিয় অ্যানিমেশন ট্র্যাক করতে এবং লিক সনাক্ত করতে দেয়।
onStart/onStop জোড়ার নিয়ম পূর্বরূপের জন্য ক্যামেরা (CameraX) এর সাথে কাজ করার ক্ষেত্রেও প্রযোজ্য। onStart এ ক্যামেরা খোলা এবং onStop এ বন্ধ করা নিশ্চিত করে যে ক্যামেরাটি অন্যান্য অ্যাপ্লিকেশনের জন্য ব্লক করা হয় না যখন আপনার অ্যাপ্লিকেশন স্ক্রিনে দৃশ্যমান নয়। এই নিয়ম লঙ্ঘন Google Play এ নেতিবাচক পর্যালোচনার একটি সাধারণ কারণ।
সচরাচর জিজ্ঞাসিত প্রশ্ন
onStart — সেই লিসেনারদের জন্য যাদের স্ক্রিন দৃশ্যমান থাকা পর্যন্ত কাজ করা উচিত (BroadcastReceiver, LocationListener, SensorListener)। onResume — সেই সম্পদের জন্য যাদের এক্সক্লুসিভ অ্যাক্সেস প্রয়োজন (ক্যামেরা, ভিডিও ক্যাপচার, বক্তব্য শনাক্তকরণ)। সিস্টেম ইভেন্ট লিসেনারদের এক্সক্লুসিভ অ্যাক্সেসের প্রয়োজন হয় না এবং তারা আংশিক ওভারল্যাপের সাথে কাজ করতে পারে — এরা onStart এ নিবন্ধিত হয়। ক্যামেরা শুধুমাত্র পূর্ণ ফোকাসের সাথে সক্রিয় হওয়া উচিত — এটি onResume এ খোলা হয়।
Activity দৃশ্যমান অবস্থায় গেলে onStart সবসময় কল হয়। onStart ছাড়া একমাত্র পরিস্থিতি — Activity তৈরি হয় এবং সাথে সাথে শেষ হয় (যেমন, onCreate এ ত্রুটির কারণে)। এই ক্ষেত্রে, onCreate এর ঠিক পরে onDestroy কল হয়। কিন্তু এটি একটি জরুরি পরিস্থিতি যা সঠিকভাবে লেখা কোডে ঘটতে হবে না।
হ্যাঁ, onStart onResume নাও পেতে পারে যদি অন্য Activity বা স্বচ্ছ উইন্ডো অবিলম্বে Activity এর উপরে খোলে। উদাহরণস্বরূপ, যদি onCreate এর পরে একটি অনুমোদন স্ক্রিন লঞ্চ করা হয় (Activity A → Activity B), তাহলে Activity A তে onStart কল হয়, কিন্তু onResume নয় — স্ক্রিন B দ্বারা ঢাকা পড়ার সাথে সাথে এটি onPause → onStop পায়।
onStart একটি Activity ইনস্ট্যান্সের জীবনে একাধিকবার কল হতে পারে। প্রতিবার যখন Activity লুকানো অবস্থা (onStop) থেকে দৃশ্যমান অবস্থায় আসে, onStart কল হয়। অনুশীলনে, সক্রিয় অ্যাপ্লিকেশন ব্যবহারের সাথে, onStart প্রতি সেশনে কয়েক ডজন বা শত শত বার কল হতে পারে।
onStart এ ডেটা লোড করা ন্যায্য যদি ডেটা স্ক্রিন উপস্থিত হলে প্রতিবার আপডেট করা উচিত। উদাহরণস্বরূপ, একটি খবরের ফিড বা বিজ্ঞপ্তির তালিকা। তবে, লোডিং অ্যাসিঙ্ক্রোনাস হওয়া উচিত — lifecycleScope সহ করুটিনের মাধ্যমে, UI থ্রেড ব্লক করা এড়াতে। যে ডেটা স্ক্রিন উপস্থিতির মধ্যে পরিবর্তিত হয় না, তার জন্য onCreate এ একবার লোড করা যথেষ্ট।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন