পাঠ ০৪ · ৫৭-এর মধ্যে · মডিউল ১
Home / Courses / Mobile App Development / ফাউন্ডেশন

মোবাইল অ্যাপ লাইফসাইকেল — স্টেট ও ট্রানজিশন

The mobile app lifecycle — states and transitions
১০ মিনিট পড়া শুরু · Beginner Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • মোবাইল অ্যাপ লাইফসাইকেলের ছয়টি স্টেট এবং প্রতিটির বাস্তব অর্থ
  • কোন স্টেট থেকে কোন স্টেটে যাওয়া বাস্তবে সম্ভব — একটি সম্পূর্ণ ALLOWED ট্রানজিশন টেবিল
  • একটি সত্যিকারের, কার্যকর Python স্টেট মেশিন যা একটি দীর্ঘ, বাস্তবসম্মত ট্রানজিশন ক্রম যাচাই করে
  • কেন কিছু "স্বাভাবিক মনে হওয়া" ট্রানজিশন (যেমন suspended থেকে সরাসরি background) আসলে অবৈধ

১ · ছয়টি স্টেট, তাদের বাস্তব অর্থ

বাস্তব মোবাইল OS (iOS/Android)-এর আচরণ থেকে অনুপ্রাণিত হয়ে, একটি অ্যাপ যেকোনো মুহূর্তে এই ছয়টি স্টেটের একটিতে থাকতে পারে:

not_running
অ্যাপ এখনো চালু হয়নি, বা সম্পূর্ণ বন্ধ — শুরুর স্টেট।
foreground
ব্যবহারকারী সরাসরি অ্যাপের স্ক্রিনে আছেন এবং ইন্টারঅ্যাক্ট করছেন।
inactive
অ্যাপ স্ক্রিনে দৃশ্যমান কিন্তু সাময়িকভাবে ইন্টারঅ্যাকশন থেকে বিচ্ছিন্ন — যেমন একটি ইনকামিং কল ব্যানার বা নোটিফিকেশন সেন্টার swipe।
background
অ্যাপ স্ক্রিনে নেই, কিন্তু OS-এর দেওয়া একটি সংক্ষিপ্ত grace period-এর জন্য এখনো কিছু কোড চালাতে পারে।
suspended
অ্যাপ মেমোরিতে আছে (দ্রুত ফিরে আসার জন্য), কিন্তু কোনো কোড আর execute হচ্ছে না — সম্পূর্ণ "জমে" থাকা অবস্থা।
killed
OS মেমোরি খালি করতে অ্যাপটিকে সম্পূর্ণ মেমোরি থেকে সরিয়ে ফেলেছে — টার্মিনাল স্টেট, নতুন করে চালু করা ছাড়া কোনো পথ নেই।

২ · বৈধ ট্রানজিশন টেবিল

প্রতিটি স্টেট থেকে শুধু নির্দিষ্ট কিছু স্টেটে যাওয়া বাস্তবসম্মত। নিচের টেবিলে প্রতিটি স্টেটের বৈধ পরবর্তী স্টেট এবং সেই ট্রানজিশনের একটি বাস্তব উদাহরণ দেওয়া হলো — এই টেবিলটিই নিচের কোড সেলের ALLOWED ডিকশনারির ভিত্তি।

বর্তমান স্টেট বৈধ পরবর্তী স্টেট বাস্তব উদাহরণ
not_running foreground ব্যবহারকারী প্রথমবার অ্যাপটি চালু করলেন
foreground inactive, background ইনকামিং কল এলো, বা ইউজার হোম বাটন চাপলেন
inactive foreground, background কল ডিসমিস হলো (ফিরে গেলেন), বা ইন্টারাপশনের সময়ই হোম বাটন চাপলেন
background foreground, suspended, killed ইউজার ফিরে এলেন, বা grace period শেষে OS suspend করলো, বা মেমোরি চাপে সরাসরি kill করলো
suspended foreground, killed ইউজার আইকনে ট্যাপ করে সরাসরি resume করলেন, বা OS মেমোরি খালি করতে kill করলো
killed — (কোনোটিই নয়) টার্মিনাল স্টেট — নতুন করে চালু করলে একটি সম্পূর্ণ নতুন AppLifecycle ইনস্ট্যান্স শুরু হয়

লক্ষ্য করুন suspended-এর তালিকায় background নেই — একটি suspended অ্যাপ সরাসরি "নীরবে ব্যাকগ্রাউন্ডে" ফিরতে পারে না, resume মানেই আবার execution শুরু করা, যা সবসময় foreground-এ ফিরেই ঘটে।

৩ · একটি বাস্তবসম্মত ট্রানজিশন ক্রম

নিচের কোড সেলে L01-এর সরল AppLifecycle ক্লাসটি সম্পূর্ণ ৬-স্টেট মডেলে সম্প্রসারিত করা হয়েছে, এবং একটি দীর্ঘ, বাস্তবসম্মত ট্রানজিশন ক্রম চালানো হয়েছে — যার মধ্যে দুটি ইচ্ছাকৃতভাবে ভুল (অবৈধ) ট্রানজিশনও আছে, যেগুলো ALLOWED টেবিল অনুযায়ী সঠিকভাবে প্রত্যাখ্যাত হয়।

Python
# L01-এর সরল ৪-স্টেট AppLifecycle সম্প্রসারিত করে বাস্তবসম্মত ৬-স্টেট মডেল
# শুধু ALLOWED টেবিলে থাকা ট্রানজিশনই বৈধ -- ঠিক যেমন বাস্তব মোবাইল OS করে

class AppLifecycle:
    ALLOWED = {
        'not_running': {'foreground'},
        'foreground':  {'inactive', 'background'},
        'inactive':    {'foreground', 'background'},
        'background':  {'foreground', 'suspended', 'killed'},
        'suspended':   {'foreground', 'killed'},
        'killed':      set(),   # টার্মিনাল স্টেট -- নতুন করে চালু করতে হয়
    }

    def __init__(self):
        self.state = 'not_running'
        self.history = [self.state]
        self.attempts = 0
        self.rejected = 0

    def transition(self, new_state, reason):
        self.attempts += 1
        if new_state in self.ALLOWED[self.state]:
            old_state = self.state
            self.state = new_state
            self.history.append(new_state)
            print(f"{reason:58s} | {old_state} -> {new_state}  (বৈধ)")
            return True
        else:
            self.rejected += 1
            print(f"{reason:58s} | {self.state} -> {new_state}  (অবৈধ, প্রত্যাখ্যাত)")
            return False

app = AppLifecycle()
app.transition('foreground', 'অ্যাপ চালু করা হলো')
app.transition('inactive', 'ইনকামিং কল ব্যানার এলো (ইন্টারাপশন শুরু)')
app.transition('foreground', 'কল ডিসমিস হলো, ইউজার অ্যাপে ফিরে এলো')
app.transition('background', 'ইউজার হোম বাটন চাপলো')
app.transition('suspended', 'grace period শেষ, OS অ্যাপকে suspend করলো')
app.transition('background', 'ভুল ধারণা: suspended থেকে সরাসরি background-এ ফেরা')
app.transition('foreground', 'ইউজার আবার অ্যাপ আইকনে ট্যাপ করলো, resume হলো')
app.transition('background', 'ইউজার আবার হোম বাটন চাপলো')
app.transition('killed', 'মেমোরি চাপে OS সরাসরি অ্যাপ বন্ধ করে দিলো (suspended ধাপ বাদ দিয়ে)')
app.transition('foreground', 'ভুল ধারণা: killed থেকে সরাসরি foreground-এ ফেরার চেষ্টা')

print(f"\nমোট স্টেট হিস্ট্রি: {app.history}")
print(f"মোট ট্রানজিশন চেষ্টা: {app.attempts} (বৈধ: {app.attempts - app.rejected}, প্রত্যাখ্যাত: {app.rejected})")

    
মোট ১০টি ট্রানজিশন চেষ্টা করা হয়েছে, যার মধ্যে ২টি অবৈধ (৫ম চেষ্টার পর suspended→background, এবং শেষ চেষ্টা killed→foreground) — তাই app.history-তে মোট ৯টি স্টেট থাকবে (শুরুর not_running + ৮টি বৈধ ট্রানজিশন): ['not_running', 'foreground', 'inactive', 'foreground', 'background', 'suspended', 'foreground', 'background', 'killed']।
মূল কথা · Key takeaway

বাস্তব মোবাইল লাইফসাইকেল L01-এর সরল ৪-স্টেট মডেলের চেয়ে অনেক বেশি সূক্ষ্ম — inactive ও suspended-এর মতো মধ্যবর্তী স্টেট আছে যেগুলো নির্দিষ্ট বাস্তবতা বোঝায়, এবং প্রতিটি স্টেট থেকে শুধু নির্দিষ্ট কিছু ট্রানজিশনই সম্ভব। একটি অ্যাপকে নির্ভরযোগ্য বানাতে হলে ডেভেলপারকে জানতে হয় ঠিক কোন স্টেটে কোন কাজ (ডেটা সেভ করা, অ্যানিমেশন থামানো, নেটওয়ার্ক কল বাতিল করা) করা দরকার — পরবর্তী মডিউলগুলোতে (M7, M9) আমরা দেখব কীভাবে স্টেট ম্যানেজমেন্ট ও নেটওয়ার্কিং এই লাইফসাইকেলের সাথে যুক্ত হয়।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ কেন suspended→background ট্রানজিশন অবৈধ — বাস্তব মোবাইল OS-ও কি একই আচরণ করে?

হ্যাঁ। suspended অবস্থায় অ্যাপের কোনো কোড execute হচ্ছে না — এটি মেমোরিতে সম্পূর্ণ "জমে" আছে। এটিকে সরাসরি background-এ (যেখানে কিছু কোড এখনও সক্রিয়ভাবে চলতে পারে) ফেরানো অর্থহীন — resume করা মানেই আবার execution শুরু করা, যা বাস্তবেও সবসময় foreground-এ ফিরেই ঘটে, এমনকি ব্যবহারকারী শুধু অ্যাপ-সুইচারে থাম্বনেইল দেখলেও প্রকৃত resume তখনই হয় যখন অ্যাপটি আবার সামনে আনা হয়।

প্র ০২ background থেকে সরাসরি killed-এ যাওয়া বৈধ — suspended ধাপ বাদ দিয়ে কি বাস্তবেও এমন হয়?

হ্যাঁ। suspended একটি সাধারণ মধ্যবর্তী ধাপ, কিন্তু বাধ্যতামূলক নয়। যদি ডিভাইসের মেমোরি তীব্র চাপে থাকে (যেমন অনেকগুলো ভারী অ্যাপ একসাথে খোলা), OS grace period বা suspended ধাপের জন্য অপেক্ষা না করেই সরাসরি একটি ব্যাকগ্রাউন্ড অ্যাপকে kill করে দিতে পারে।

প্র ০৩ inactive স্টেটটি foreground থেকে আলাদা করে রাখা হলো কেন — L01-এর সরল ৪-স্টেট মডেলে তো এটি ছিল না?

L01-এর মডেল ইচ্ছাকৃতভাবে সরলীকৃত ছিল, শুধু মূল ধারণাটি (ফোরগ্রাউন্ড-ব্যাকগ্রাউন্ড-কিল) বোঝানোর জন্য। বাস্তবে একটি অ্যাপ স্ক্রিনে দৃশ্যমান থেকেও সাময়িকভাবে ইন্টারঅ্যাকশন থেকে বিচ্ছিন্ন হতে পারে — যেমন ইনকামিং কল ব্যানার বা নোটিফিকেশন সেন্টার swipe করার সময়। এই মুহূর্তগুলোতে অনেক অ্যাপ অ্যানিমেশন/অডিও পজ করে রাখে, তাই এটিকে "সম্পূর্ণ সক্রিয় ফোরগ্রাউন্ড" থেকে আলাদা স্টেট হিসেবে রাখা দরকার।

অনুশীলন

  1. চিন্তা করুন: একটি মিউজিক প্লেয়ার অ্যাপ ব্যবহারকারী হোম বাটন চাপার পরও ব্যাকগ্রাউন্ডে গান বাজাতে থাকে। উপরের মডেলে background স্টেট শুধু একটি সংক্ষিপ্ত grace period বোঝায় — তাহলে এই দীর্ঘস্থায়ী ব্যাকগ্রাউন্ড আচরণ কীভাবে সম্ভব বলে আপনার মনে হয়?

    বাস্তব মোবাইল OS নির্দিষ্ট কিছু ব্যাকগ্রাউন্ড টাস্ক টাইপকে (যেমন অডিও প্লেব্যাক, লোকেশন ট্র্যাকিং, ডাউনলোড) বিশেষ অনুমতি দেয়, যাতে সেগুলো সাধারণ grace period পার হয়ে যাওয়ার পরও চলতে পারে। এই সরলীকৃত মডেলে আমরা সব background অ্যাপকে একইভাবে treat করেছি, কিন্তু বাস্তবে ব্যাকগ্রাউন্ড টাস্কের ধরন অনুযায়ী OS-এর আচরণ ভিন্ন হয় — এটি M9 (ব্যাকগ্রাউন্ড সিঙ্ক)-এ বিস্তারিত আলোচনা করা হবে।

  2. পরীক্ষা করুন: উপরের কোড সেলে ALLOWED['inactive']-এ 'killed' যোগ করুন (ধরে নিন অ্যাপ ইন্টারাপশনের সময়ও ক্র্যাশ করতে পারে), তারপর inactive স্টেটে থাকা অবস্থায় app.transition('killed', 'অ্যাপ ক্র্যাশ করলো ইন্টারাপশনের সময়') কল করে দেখুন এটি এখন বৈধ হয় কি না।

    ALLOWED['inactive']-কে {'foreground', 'background', 'killed'}-এ পরিবর্তন করার পর, inactive স্টেট থেকে 'killed'-এ ট্রানজিশন এখন বৈধ হবে এবং "(বৈধ)" প্রিন্ট হবে, আর app.rejected-এর মান বাড়বে না সেই কলের জন্য — দেখাচ্ছে ALLOWED ডিকশনারিই একমাত্র জায়গা যেখানে পুরো স্টেট মেশিনের আচরণ নির্ধারিত হয়।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

  • কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ অ্যাপ লাইফসাইকেল, মোবাইল UI/UX, MVVM/MVI আর্কিটেকচার, নেটিভ বনাম ক্রস-প্ল্যাটফর্ম, নেভিগেশন, স্টেট ম্যানেজমেন্ট, লোকাল স্টোরেজ, ডিভাইস ফিচার ও ডিপ্লয়মেন্ট — বাকি পাঠগুলো শীঘ্রই যুক্ত হবে।
  • Full-Stack Web Frameworks কোর্স সহোদর কোর্স MVC/MVVM, স্টেট ম্যানেজমেন্ট, টেস্টিং ও CI/CD-র সাধারণ আর্কিটেকচারাল ভিত্তি সেই কোর্সেই তৈরি হয়েছে — এই কোর্স মোবাইল-নির্দিষ্ট পার্থক্য শেখায়।
  • সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design, Cybersecurity, Cloud Computing & DevOps, Computer Networks, Operating Systems, Computer Architecture, Programming Languages & Compiler Design, Software Engineering & Git, Theory of Computation, Engineering Economics, Full-Stack Web Frameworks ও Mobile App Development — সব এক জায়গায়।
আগের পাঠ
মোবাইল অ্যাপের ধরন ও কখন কোনটি ব্যবহার করবেন