onDestroy: এটি কী, Android-এ Activity-র কাজ শেষ করা

লেখক: IT Sectr প্রকাশিত: 2026-03-04 পড়ার সময়: 8 মিনিট

onDestroy — Android-এ Activity এবং Fragment-এর জীবনচক্রের চূড়ান্ত পদ্ধতি, যা উপাদানের সম্পূর্ণ ধ্বংসের আগে কল করা হয়। onDestroy সংকেত দেয় যে Activity বা Fragment তার কাজ শেষ করছে: সমস্ত রিসোর্স মুক্ত করতে হবে, নেস্টেড ফ্র্যাগমেন্টগুলি ধ্বংস করতে হবে, ViewModel পরিষ্কার করতে হবে। Google-এর মতে, Activity সমাপ্তির 100% ক্ষেত্রে onDestroy কল করা হয়, কিন্তু প্রক্রিয়া মৃত্যুর (process death) সময় সিস্টেম onDestroy কল সম্পূর্ণরূপে এড়িয়ে যেতে পারে। onDestroy-এ Android ডকুমেন্টেশন জোর দেয় যে এই পদ্ধতি অস্বাভাবিক সমাপ্তিতে কলের গ্যারান্টি দেয় না।

মূল বিষয়

  • onDestroy — Activity বা Fragment ধ্বংসের আগে শেষ কল, চূড়ান্ত রিসোর্স ক্লিনআপের জন্য উদ্দিষ্ট।
  • সিস্টেম দ্বারা প্রক্রিয়া মৃত্যুর সময় onDestroy কল নিশ্চিত নয় — গুরুত্বপূর্ণ ডেটা সংরক্ষণের জন্য এটির উপর নির্ভর করবেন না।
  • onDestroy-এ ব্যাকগ্রাউন্ড টাস্ক বাতিল করা, সকেট এবং ডেটাবেস বন্ধ করা, ViewModelStore পরিষ্কার করা প্রয়োজন।
  • onStop থেকে পার্থক্য: onStop — দৃশ্যমানতা হারানো (Activity মেমরিতে জীবিত), onDestroy — সম্পূর্ণ ধ্বংস।
  • onDestroy-এ isFinishing() দেখায় যে Activity ব্যবহারকারীর কমান্ড (finish()) বা সিস্টেমের সিদ্ধান্তে শেষ হচ্ছে।

onDestroy: Android-এ এটি কী?

onDestroy — একটি কলব্যাক পদ্ধতি যা Android সম্পূর্ণরূপে Activity বা Fragment ধ্বংস করার আগে কল করে। এটি ডেভেলপারের জন্য রিসোর্স মুক্ত করা, ব্যাকগ্রাউন্ড অপারেশন বাতিল করা এবং ডেটা কাজ শেষ করার শেষ সুযোগ। onDestroy কার্যকর করার পর, Activity/Fragment ইনস্ট্যান্স আবর্জনা সংগ্রহ (GC) এর জন্য চিহ্নিত হয় এবং আর ব্যবহার করা যায় না।

onDestroy কল করার কারণ:

  • স্পষ্ট finish() কল — ব্যবহারকারী “পিছনে” চাপলেন বা ডেভেলপার finishActivity() কল করলেন।
  • স্ক্রিন রোটেশন — Activity ধ্বংস হয় এবং নতুন কনফিগারেশন দিয়ে পুনরায় তৈরি হয়।
  • কনফিগারেশন পরিবর্তন — কীবোর্ড, ভাষা পরিবর্তন, স্ক্রিন আকার পরিবর্তন (মাল্টি-উইন্ডো)।
  • সিস্টেমের সিদ্ধান্ত — Android রিসোর্স মুক্ত করতে Activity মেরে ফেলে (কিন্তু onDestroy কল নাও হতে পারে)।

Google Android Vitals পরিসংখ্যান (2025) অনুসারে, সমস্ত Activity ধ্বংসের ঘটনার প্রায় 12% স্ক্রিন রোটেশনের কারণে, 65% finish()-এর কারণে এবং 23% কনফিগারেশন পরিবর্তনের কারণে ঘটে। onDestroy এড়িয়ে যাওয়া প্রক্রিয়া মৃত্যুর শতাংশ কম RAM (4 GB-এর কম) যুক্ত ডিভাইসের উপর নির্ভর করে প্রায় 5–8%

কখন onDestroy কল করা হয় — এবং কখন কল করা হয় না

onDestroy বেশিরভাগ সাধারণ পরিস্থিতিতে কল করা হয়, তবে গুরুত্বপূর্ণ ব্যতিক্রম রয়েছে যা ডেভেলপারকে বিবেচনা করতে হবে। onDestroy কলের গ্যারান্টি বোঝা অ্যাপ্লিকেশন আর্কিটেকচারের জন্য গুরুত্বপূর্ণ, বিশেষ করে ডেটা সংরক্ষণ এবং WorkManager কাজ বাতিল করার জন্য।

কখন onDestroy কল করা হয়:

  • ব্যবহারকারী “পিছনে” বাটন চাপলেন — Activity.finish() → onPause → onStop → onDestroy।
  • স্ক্রিন রোটেশন — Activity ধ্বংস হয় (onPause → onStop → onDestroy), তারপর পুনরায় তৈরি হয়।
  • কনফিগারেশন পরিবর্তন — সিস্টেম সেটিং যা Activity পুনর্নির্মাণ প্রয়োজন।
  • finishAffinity() কল করা — স্ট্যাকের সমস্ত Activities শেষ করা।
  • FragmentManager থেকে Fragment সরানো — Fragment পায়: onPause → onStop → onDestroyView → onDestroy → onDetach।

কখন onDestroy কল করা হয় না:

  • সিস্টেম দ্বারা প্রক্রিয়া মৃত্যু — Android মেমরি কম হলে পুরো অ্যাপ্লিকেশন প্রক্রিয়া মেরে ফেলে। Activity onDestroy পায় না কারণ প্রক্রিয়া Linux কার্নেল স্তরে শেষ হয়।
  • অস্বাভাবিক সমাপ্তি — মূল থ্রেডে অনক্যাচড এক্সেপশন onDestroy কল না করেই অ্যাপ্লিকেশন মেরে ফেলে।
  • ফোর্স স্টপ — ব্যবহারকারী সেটিংসে জোর করে অ্যাপ্লিকেশন বন্ধ করে।

onDestroy কলের গ্যারান্টির অভাবের কারণে, Google সুপারিশ করে: গুরুত্বপূর্ণ ডেটা সংরক্ষণের জন্য কখনই onDestroy-এর উপর নির্ভর করবেন না। onSaveInstanceState(), WorkManager বা স্বয়ংক্রিয় সংরক্ষণ সহ Room ব্যবহার করুন। onDestroy রিসোর্স মুক্ত করার জন্য, স্থায়িত্বের (persistence) জন্য নয়।

Activity এবং Fragment-এ onDestroy: মিল এবং পার্থক্য

onDestroy Activity এবং Fragment উভয়ের জন্যই বিদ্যমান, তবে ভিন্ন চুক্তির সাথে। Fragment-এর জীবনচক্র আরও বিশদ: onDestroy ছাড়াও, onDestroyView (View স্তরবিন্যাস ধ্বংস) এবং onDetach (Activity থেকে বিচ্ছিন্ন) রয়েছে।

উপাদানধ্বংসের পদ্ধতিক্রমViewModel বেঁচে থাকে
ActivityonDestroyonPause → onStop → onDestroyনা (কেবল যদি ViewModelStore সংরক্ষিত না হয়)
FragmentonDestroyView, onDestroy, onDetachonPause → onStop → onDestroyView → onDestroy → onDetachহ্যাঁ, যদি Fragment সরানো না হয়

মূল পার্থক্য: Fragment-এর View নিজের Fragment-এর চেয়ে বেশি বার পুনরায় তৈরি হয়। স্ক্রিন রোটেশনের সময়, Fragment onDestroyView (View ধ্বংস) এর মধ্য দিয়ে যায়, কিন্তু Fragment নিজে এবং এর ViewModel জীবিত থাকে। onDestroyView মেমরি লিক এড়াতে View রেফারেন্স পরিষ্কার করার সঠিক জায়গা। Fragment-এর onDestroy Activity-র onDestroy-এর অনুরূপ, যা Fragment সম্পূর্ণরূপে সরানো হলে কল করা হয়।

চাইল্ড ফ্র্যাগমেন্টগুলি প্যারেন্ট Fragment-এর onDestroy-এর আগে ধ্বংস হয়। Activity-তে, চাইল্ড ফ্র্যাগমেন্টগুলি onDestroy পায় যখন প্যারেন্ট Activity-র onDestroy কল করা হয়। ক্রম নিশ্চিত: ফ্র্যাগমেন্টগুলি ধারণকারী Activity-র আগে শেষ হয়।

onDestroy-এ কী করবেন: পরিষ্কার করার চেকলিস্ট

onDestroy সেই সমস্ত রিসোর্স মুক্ত করার জন্য যা Activity বা Fragment-এর বেশি বেঁচে থাকা উচিত নয়। onStop-এর বিপরীতে, যা ফিরে আসা পর্যন্ত রিসোর্স মুক্ত করে, onDestroy চূড়ান্ত পরিষ্কার করে।

onDestroy-এ বাধ্যতামূলক কাজের চেকলিস্ট:

  • কোরুটিন এবং Flow বাতিল করুন — যে jobs viewModelScope-এর সাথে আবদ্ধ নয় সেগুলি বাতিল করুন। viewModelScope স্বয়ংক্রিয়ভাবে বাতিল হয়, কিন্তু lifecycleScope Activity-র জীবনচক্রের সাথে আবদ্ধ।
  • সকেট এবং চ্যানেল বন্ধ করুন — WebSocket (OkHttp), BluetoothSocket, ServerSocket। ধ্বংসের পর এগুলি খোলা রাখা সিস্টেম রিসোর্স লিক।
  • ফাইল এবং স্ট্রিম বন্ধ করুন — FileInputStream, FileOutputStream, Cursor। Cursor ContentProvider-এ ANR ঘটাতে পারে যদি বন্ধ না করা হয়।
  • ContentObserver থেকে সদস্যতা বাতিল করুন — যদি Activity বিষয়বস্তু পরিবর্তন (যোগাযোগ, মিডিয়া লাইব্রেরি) দেখছে।
  • BroadcastReceiver নিবন্ধনমুক্ত করুন — গতিশীলভাবে নিবন্ধিত রিসিভারগুলি বাতিল করা উচিত।
  • ডেটাবেস বন্ধ করুন — Room অ্যাপ্লিকেশন ধ্বংস হলে স্বয়ংক্রিয়ভাবে সংযোগ বন্ধ করে, কিন্তু সরাসরি SQLiteDatabase-এ ম্যানুয়াল close() প্রয়োজন।

onDestroy-এ কী করবেন না: onDestroy-এ ডেটা সংরক্ষণ করবেন না — onPause বা onSaveInstanceState ব্যবহার করুন। নতুন Service বা WorkManager কাজ শুরু করবেন না — Activity ধ্বংস হবে এবং আপনি ফলাফল ট্র্যাক করতে পারবেন না। UI আপডেট করার চেষ্টা করবেন না — View স্তরবিন্যাস ইতিমধ্যে ধ্বংস বা ধ্বংস হওয়ার প্রক্রিয়ায় আছে; findViewById() কল করলে null ফিরে আসবে।

onDestroy এবং ViewModel: একসাথে কাজ করা

ViewModel স্ক্রিন রোটেশনের সময় Activity-র onDestroy থেকে বাঁচার জন্য ডিজাইন করা হয়েছে, কিন্তু finish()-এর সময় Activity-র সাথে ধ্বংস হয়। এই অসমমিতিক আচরণ ডেভেলপারদের মধ্যে বিভ্রান্তির প্রধান কারণ।

স্ক্রিন রোটেশনের সময়:

  • Activity: onPause → onStop → onDestroy (Activity ধ্বংস)।
  • ViewModel: ধ্বংস হয়নি — ViewModelStore সংরক্ষিত হয় এবং নতুন Activity-তে পাঠানো হয়।
  • নতুন Activity: onCreate → onStart → onResume, একই ViewModel পায়।

finish()-এর সময় (ব্যবহারকারী “পিছনে” চাপলেন):

  • Activity: onPause → onStop → onDestroy।
  • ViewModel: onCleared() — Activity-র onDestroy-এর পরে কল হয়।
  • সমস্ত viewModelScope কোরুটিন স্বয়ংক্রিয়ভাবে বাতিল হয়।

অতএব, onDestroy-এ viewModelScope বাতিল করা প্রয়োজন নয় — ViewModel নিজেই এটি করবে। আপনি যদি lifecycleScope (Activity-র সাথে আবদ্ধ, ViewModel-এর সাথে নয়) ব্যবহার করেন, তাহলে onDestroy-এ lifecycleScope.cancel() এর মাধ্যমে এটি বাতিল করুন অথবা Job ম্যানুয়ালি পরিচালনা করুন।

Kotlin-এ onDestroy সহ কোড উদাহরণ

উদাহরণ 1: lifecycleScope কোরুটিন বাতিল সহ onDestroy Activity

Activity-তে সঠিক lifecycleScope ব্যবস্থাপনা দেখায়: নেটওয়ার্ক অবস্থা পর্যবেক্ষণের জন্য একটি কোরুটিন চালু হয় এবং onDestroy-এ বাতিল হয়।

kotlin
class NetworkMonitorActivity : AppCompatActivity() {
    private val networkCallback = object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) {
            Log.d("NetworkMonitor", "নেটওয়ার্ক উপলব্ধ")
        }
        override fun onLost(network: Network) {
            Log.d("NetworkMonitor", "নেটওয়ার্ক হারিয়ে গেছে")
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_network)
        val connectivityManager = getSystemService(ConnectivityManager::class.java)
        connectivityManager.registerDefaultNetworkCallback(networkCallback)
        lifecycleScope.launch {
            Log.d("NetworkMonitor", "নেটওয়ার্ক পর্যবেক্ষণ শুরু হয়েছে")
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        val connectivityManager = getSystemService(ConnectivityManager::class.java)
        connectivityManager.unregisterNetworkCallback(networkCallback)
        Log.d("NetworkMonitor", "onDestroy: কলব্যাক বাতিল করা হয়েছে")
    }
}

onDestroy-এ, নেটওয়ার্ক কলব্যাক নিবন্ধন বাতিল করা হয়। lifecycleScope জীবনচক্র ধ্বংস হলে স্বয়ংক্রিয়ভাবে বাতিল হয় — আলাদা কোরুটিন বাতিলের প্রয়োজন নেই। নেটওয়ার্ক কলব্যাক নিবন্ধনমুক্ত করতে হবে, অন্যথায় Activity ধ্বংসের পরও এটি সিস্টেমে থাকবে।

উদাহরণ 2: View রেফারেন্স পরিষ্কার সহ onDestroy Fragment

Fragment onDestroyView-এ View রেফারেন্স সঠিকভাবে পরিষ্কার করে, ক্লোজারের কারণে মেমরি লিক প্রতিরোধ করে।

kotlin
class ProfileFragment : Fragment() {
    private var avatarView: ImageView? = null
    private var progressBar: ProgressBar? = null
    private val imageLoader = ImageLoader()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        avatarView = view.findViewById(R.id.avatar)
        progressBar = view.findViewById(R.id.progress)
        loadProfile()
    }

    private fun loadProfile() {
        viewLifecycleOwner.lifecycleScope.launch {
            try {
                progressBar?.visibility = View.VISIBLE
                val bitmap = imageLoader.load("https://example.com/avatar.png")
                avatarView?.setImageBitmap(bitmap)
            } finally {
                progressBar?.visibility = View.GONE
            }
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        avatarView = null
        progressBar = null
        imageLoader.cancel()
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d("ProfileFragment", "onDestroy: Fragment সম্পূর্ণরূপে ধ্বংস হয়েছে")
    }
}

onDestroyView-এ, View রেফারেন্স null এ সেট করা হয় — এটি মেমরি লিক প্রতিরোধ করে যদি imageLoader-এ ক্লোজার avatarView-এর রেফারেন্স ধরে রাখে। Fragment নিজে এবং এর ViewModel onDestroy পর্যন্ত জীবিত থাকে। imageLoader.cancel() লোডিং বাতিল করে যদি Fragment স্ক্রিন ছেড়ে যায়।

উদাহরণ 3: onDestroy-এ isFinishing পরীক্ষা

isFinishing() ব্যবহার করে পার্থক্য করা যায় যে Activity ব্যবহারকারীর কমান্ডে শেষ হচ্ছে নাকি পুনর্নির্মাণের জন্য।

kotlin
class AnalyticsActivity : AppCompatActivity() {
    private val analytics = Analytics()

    override fun onDestroy() {
        if (isFinishing) {
            Log.d("AnalyticsActivity", "Activity finish() দিয়ে শেষ হচ্ছে — বিশ্লেষণ পাঠানো হচ্ছে")
            analytics.sendSessionEnd()
        } else {
            Log.d("AnalyticsActivity", "Activity পুনরায় তৈরি হচ্ছে (রোটেশন/কনফিগারেশন) — বিশ্লেষণ পাঠানো হচ্ছে না")
        }
        super.onDestroy()
    }
}

isFinishing() পরীক্ষা করা বিশ্লেষণ, লগিং এবং সেশন ডেটা পরিষ্কারের জন্য একটি গুরুত্বপূর্ণ প্যাটার্ন। রোটেশনের সময়, সেশন শেষ ইভেন্ট পাঠানো উচিত নয় — ব্যবহারকারী এখনও অ্যাপ্লিকেশনের সাথে কাজ করছে। Google Analytics অনুসারে, ভুল isFinishing() পরীক্ষা 40% মিথ্যা সেশন ইভেন্টের কারণ।

সচরাচর জিজ্ঞাসিত প্রশ্ন

onDestroy কল নাও হতে পারে?

হ্যাঁ, হতে পারে — সিস্টেম দ্বারা প্রক্রিয়া মৃত্যু, ব্যবহারকারী দ্বারা ফোর্স স্টপ বা অস্বাভাবিক সমাপ্তির সময়। Google-এর মতে, প্রায় 5–8% Activity সমাপ্তি onDestroy কল ছাড়াই ঘটে। ডেভেলপারদের গুরুত্বপূর্ণ ডেটা সংরক্ষণের জন্য onDestroy-এর উপর নির্ভর করা উচিত নয় — onPause বা onSaveInstanceState ব্যবহার করুন।

onDestroy এবং finish()-এর মধ্যে পার্থক্য কী?

finish() — একটি কল যা Activity ধ্বংস শুরু করে। onDestroy — একটি কলব্যাক যা finish() কার্যকর করার সময় কল হয়। সাধারণ সমাপ্তিতে onDestroy কল হওয়ার জন্য finish() প্রয়োজন। finish() সিস্টেম বা ডেভেলপার দ্বারা কল করা যেতে পারে, onDestroy কেবল একটি সিস্টেম কলব্যাক।

আমার কি Fragment-এ super.onDestroy() কল করতে হবে?

হ্যাঁ, অবশ্যই Activity এবং Fragment উভয়েই। super.onDestroy() ChildFragmentManager, LoaderManager এবং অন্যান্য সিস্টেম উপাদানের সঠিক পরিষ্কার নিশ্চিত করে। super.onDestroy() এড়িয়ে গেলে মেমরি লিক এবং ফ্র্যাগমেন্ট পুনরুদ্ধারে ত্রুটি হয়।

onDestroy-এর সাপেক্ষে ViewModel-এ onCleared() কখন কল হয়?

onCleared() Activity বা Fragment-এর onDestroy-এর পরে কল হয়, যখন ViewModel-এর আর প্রয়োজন নেই। স্ক্রিন রোটেশনের সময়, onCleared() কল হয় না — ViewModel onDestroy থেকে বেঁচে যায়। ক্রম: Activity/Fragment-এর onDestroy → (ViewModelStore পরিষ্কার হয়) → onCleared()।

আমি কি onDestroy থেকে Service শুরু করতে পারি?

প্রযুক্তিগতভাবে হ্যাঁ, তবে সুপারিশ করা হয় না। Activity onDestroy-এর পরপরই ধ্বংস হয়ে যায়, এবং শুরু করা Service নিয়ন্ত্রণহীন থাকে। ব্যাকগ্রাউন্ড কাজের জন্য, বিলম্ব সহ WorkManager ব্যবহার করুন: WorkManager Activity শেষ হওয়ার পরেও কার্যকর করার গ্যারান্টি দেয় এবং প্রক্রিয়া মৃত্যু থেকে বেঁচে যায়।

সারসংক্ষেপ

  • onDestroy — Activity এবং Fragment-এর চূড়ান্ত জীবনচক্র কলব্যাক, উপাদানের সম্পূর্ণ ধ্বংসের আগে কল করা হয়।
  • onDestroy কল প্রক্রিয়া মৃত্যুর সময় নিশ্চিত নয় — প্রায় 5–8% সমাপ্তি এটি ছাড়া ঘটে।
  • onDestroy-এ মুক্ত করুন: নেটওয়ার্ক কলব্যাক, সকেট, ফাইল স্ট্রিম, BroadcastReceiver, ContentObserver।
  • ViewModel.onCleared() Activity-র onDestroy-এর পরে কল হয় — viewModelScope স্বয়ংক্রিয়ভাবে বাতিল হয়।
  • Fragment-এ onDestroyView (onDestroy থেকে আলাদা) — View রেফারেন্স null করার সঠিক জায়গা।
  • onDestroy-এ isFinishing() পরীক্ষা finish() সমাপ্তিকে কনফিগারেশন পরিবর্তনের কারণে পুনর্নির্মাণ থেকে আলাদা করতে দেয়।
  • ডেটা সংরক্ষণের জন্য onDestroy-এর উপর নির্ভর করবেন না — onPause বা onSaveInstanceState ব্যবহার করুন।

আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব

IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।

প্রকল্প নিয়ে আলোচনা করুন

আরও পড়ুন