LifecycleOwner — چیست، رابط Jetpack و اشتراک رویدادها

نویسنده: IT Sectr منتشر شده: 2026-03-06 زمان مطالعه: 9 دقیقه

LifecycleOwner — یک رابط کلیدی از کتابخانه Android Jetpack است که اعلام می‌کند یک شیء دارای چرخه حیات است و از طریق متد getLifecycle() به آن دسترسی فراهم می‌کند. این رابط در پایه معماری کامپوننتی برنامه‌های مدرن اندروید قرار دارد و اجازه می‌دهد منطق کار با چرخه حیات از پیاده‌سازی مشخص Activity یا Fragment جدا شود. طبق داده‌های Google I/O 2024، بیش از 85٪ پروژه‌های جدید در اندروید از LifecycleOwner برای مدیریت اشتراک‌ها و جلوگیری از نشت حافظه استفاده می‌کنند. این رابط پایه‌ای برای LiveData، ViewModel و سایر کامپوننت‌های Jetpack است و اجرای ایمن کد را فقط در حالت فعال کامپوننت تضمین می‌کند.

نکات اصلی

  • LifecycleOwner — رابط Jetpack که دسترسی به شیء Lifecycle را فراهم می‌کند
  • به طور پیش‌فرض در Activity و Fragment از AndroidX AppCompat پیاده‌سازی شده است
  • اجازه اشتراک رویدادها را از طریق LifecycleObserver و DefaultLifecycleObserver می‌دهد
  • از نشت حافظه جلوگیری می‌کند — مشاهده‌گرها هنگام نابودی به طور خودکار لغو اشتراک می‌شوند
  • در ViewModel، LiveData و سایر کامپوننت‌های Jetpack برای کار ایمن استفاده می‌شود

LifecycleOwner چیست؟

LifecycleOwner — یک رابط از بسته androidx.lifecycle است که حاوی یک متد واحد getLifecycle() است که شیء Lifecycle را برمی‌گرداند. این شیء وضعیت فعلی کامپوننت (CREATED, STARTED, RESUMED, DESTROYED) را追踪 می‌کند و در هنگام تغییر آن همه مشاهده‌گرهای مشترک را مطلع می‌کند. LifecycleOwner بخشی از Architecture Components است و در کتابخانه lifecycle-runtime قرار دارد.

وظیفه اصلی رابط — استانداردسازی دسترسی به چرخه حیات است. قبل از ظهور Jetpack، توسعه‌دهندگان از اشتراک دستی در onStart و لغو اشتراک در onStop استفاده می‌کردند که منجر به تکرار کد و خطاها می‌شد. LifecycleOwner این مشکل را با ارائه یک مکانیسم واحد برای تمام کامپوننت‌های اندروید حل می‌کند. به جای فراخوانی صریح متدهای چرخه حیات، توسعه‌دهنده یک بار در Lifecycle مشترک می‌شود و اعلان‌ها به طور خودکار می‌رسند.

این رابط در Kotlin به عنوان یک رابط تابعی با یک متد انتزاعی اعلام شده است:

kotlin
interface LifecycleOwner {
    val lifecycle: Lifecycle
}

به دلیل ماهیت تابعی رابط، پیاده‌سازی آن با استفاده از delegate یا لامبدا آسان است. این به ویژه برای ایجاد Custom Views و کلاس‌های ViewModel که باید به تغییرات چرخه حیات میزبان واکنش نشان دهند، مناسب است. شیء Lifecycle به دست آمده از getLifecycle() متدهای addObserver و removeObserver را برای مدیریت اشتراک‌ها فراهم می‌کند.

LifecycleOwner چگونه کار می‌کند

LifecycleOwner در ترکیب با دو کلاس کلیدی کار می‌کند: Lifecycle و LifecycleObserver. Lifecycle وضعیت فعلی کامپوننت را به صورت enum State (INITIALIZED, CREATED, STARTED, RESUMED, DESTROYED) ذخیره می‌کند و انتقال بین آنها را追踪 می‌کند. هنگامی که وضعیت تغییر می‌کند، Lifecycle همه مشاهده‌گرهای ثبت‌شده را مطلع می‌کند و متدهای حاشیه‌نویسی شده مربوطه را فراخوانی می‌کند. این مکانیسم "lifecycle-aware" نامیده می‌شود — کد فقط زمانی اجرا می‌شود که کامپوننت در وضعیت مناسب باشد.

مکانیسم انتقال رویدادها بر اساس الگوی Observer است. LifecycleOwner نقش Observable را ایفا می‌کند و پیاده‌سازی LifecycleObserver نقش Observer را. Activity یا Fragment هنگام تغییر وضعیت خود (onCreate → onStart → onResume → onPause → onStop → onDestroy) از طریق مکانیسم داخلی ReportFragment که به طور خودکار به سیستم AndroidX اضافه می‌شود، Lifecycle را مطلع می‌کند. توسعه‌دهنده نیازی به فراخوانی دستی متدهای Lifecycle ندارد — همه چیز به طور خودکار انجام می‌شود.

وضعیت Lifecycleرویدادمتد چرخه حیات اندروید
INITIALIZEDقبل از onCreate
CREATEDON_CREATEonCreate
STARTEDON_STARTonStart
RESUMEDON_RESUMEonResume
STARTEDON_PAUSEonPause
CREATEDON_STOPonStop
DESTROYEDON_DESTROYonDestroy

جزئیات مهم: Lifecycle تضمین می‌کند که رویدادهای ON_STOP و ON_DESTROY حتی در صورت خاتمه اضطراری فرآیند تحویل داده می‌شوند. این LifecycleOwner را به ابزاری قابل اعتماد برای آزادسازی منابع بحرانی تبدیل می‌کند. برای ذخیره‌سازی معمولی وضعیت، توصیه می‌شود از SavedStateHandle در ViewModel استفاده کنید، اما LifecycleOwner سطح پایه‌ای امنیت را فراهم می‌کند.

LifecycleObserver و DefaultLifecycleObserver

دو روش برای اشتراک رویدادهای LifecycleOwner وجود دارد: کلاسیک LifecycleObserver با حاشیه‌نویسی و مدرن DefaultLifecycleObserver با متدهای صریح. رویکرد دوم از سال 2022 توسط Google توصیه می‌شود، زیرا امنیت نوع بهتری ارائه می‌دهد و از بازتاب (reflection) که در رویکرد حاشیه‌نویسی استفاده می‌شد، اجتناب می‌کند. DefaultLifecycleObserver نیاز به Java 8+ یا Kotlin دارد و برای پروژه‌های جدید ترجیح داده می‌شود.

مثال اشتراک از طریق DefaultLifecycleObserver:

kotlin
class MyObserver : DefaultLifecycleObserver {
    override fun onStart(owner: LifecycleOwner) {
        // راه‌اندازی ردیابی GPS فقط زمانی که کامپوننت فعال است
        startLocationUpdates()
    }

    override fun onStop(owner: LifecycleOwner) {
        // توقف ایمن هنگام انتقال به حالت پس‌زمینه
        stopLocationUpdates()
    }
}

// اتصال:
lifecycleOwner.lifecycle.addObserver(MyObserver())

هر متد DefaultLifecycleObserver LifecycleOwner را به عنوان پارامتر دریافت می‌کند. این به مشاهده‌گر اجازه می‌دهد بدون نیاز به ارسال جداگانه به زمینه کامپوننت در حال اجرا دسترسی پیدا کند. این رویکرد کد را ماژولارتر و قابل آزمایش‌تر می‌کند — Observer به پیاده‌سازی مشخص Activity یا Fragment وابسته نیست، بلکه با انتزاع LifecycleOwner کار می‌کند.

رویکرد حاشیه‌نویسی LifecycleObserver

روش قدیمی با استفاده از حاشیه‌نویسی @OnLifecycleEvent هنوز در پروژه‌های legacy دیده می‌شود، اما استفاده از آن برای کد جدید توصیه نمی‌شود. بازتاب مورد نیاز برای پردازش حاشیه‌نویسی‌ها سربار اضافه می‌کند و می‌تواند منجر به خطاهایی شود که در مرحله کامپایل شناسایی نمی‌شوند. Google به طور رسمی مهاجرت به DefaultLifecycleObserver را توصیه می‌کند.

kotlin
// رویکرد قدیمی — برای پروژه‌های جدید توصیه نمی‌شود
class MyLegacyObserver : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onStart() {
        startLocationUpdates()
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onStop() {
        stopLocationUpdates()
    }
}

رویکرد حاشیه‌نویسی یک نقص اساسی دارد: عدم کنترل طول عمر Observer. اگر توسعه‌دهنده فراموش کند Observer را هنگام نابودی LifecycleOwner لغو اشتراک کند، شیء Observer تا زمانی که جمع‌آوری زباله اجرا شود در حافظه باقی می‌ماند. DefaultLifecycleObserver این مشکل را حل می‌کند — Observer به Lifecycle متصل است و هنگام انتقال به وضعیت DESTROYED به طور خودکار لغو اشتراک می‌شود.

LifecycleOwner در Activity و Fragment

از AppCompat 1.1.0 و AndroidX Fragment 1.2.0 به بعد، تمام Activity و Fragment که از AppCompatActivity یا Fragment ارث می‌برند به طور خودکار LifecycleOwner هستند. این بدان معناست که متد getLifecycle() به طور پیش‌فرض در آنها در دسترس است و اشتراک رویدادهای چرخه حیات بدون پیکربندی اضافی کار می‌کند. توسعه‌دهنده فقط باید lifecycle.addObserver() را از هر جایی در Activity یا Fragment فراخوانی کند.

مثال ادغام LifecycleOwner در Activity:

kotlin
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycle.addObserver(LocationObserver(this))
    }
}

در این مثال lifecycle یک extension property است که به لطف AndroidX Activity در دسترس است. Observer LocationObserver به طور خودکار اعلان‌هایی درباره شروع (ON_START) و توقف (ON_STOP) Activity دریافت می‌کند. هنگام چرخش صفحه، Observer از ON_DESTROY و سپس ON_CREATE مطلع می‌شود که به پردازش صحیح تغییرات پیکربندی بدون کد اضافی کمک می‌کند.

LifecycleOwner در Fragment

Fragment LifecycleOwner را از طریق رابط پیاده‌سازی می‌کند و Lifecycle آن به چرخه حیات Fragment متصل است، نه Activity والد. این مهم است: Lifecycle Fragment وقتی Fragment از تراکنش حذف می‌شود به DESTROYED می‌رود، در حالی که Activity ممکن است در RESUMED باقی بماند. این تفاوت به Observer اجازه می‌دهد به طور جداگانه در چرخه حیات هر کامپوننت مشترک شود.

kotlin
class MyFragment : Fragment() {
    private val uiStateObserver = UiStateObserver()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        lifecycle.addObserver(uiStateObserver)
    }
}

مزیت مهم استفاده از LifecycleOwner در Fragment — لغو اشتراک خودکار هنگام انتقال Fragment به DESTROYED. این به ویژه برای ViewPager که در آن Fragment‌ها ممکن است به صورت پویا ایجاد و نابود شوند، مرتبط است. مدیریت دستی اشتراک‌ها در این سناریو بسیار پیچیده و مستعد خطا بود.

ایجاد LifecycleOwner سفارشی

رابط LifecycleOwner را می‌توان در هر کلاسی که چرخه حیات دارد پیاده‌سازی کرد. این برای Custom Views، Service و حتی ViewModel در برخی راه‌حل‌های معماری مفید است. Google کلاس کمکی LifecycleRegistry را ارائه می‌دهد که وضعیت Lifecycle را مدیریت می‌کند و رویدادها را تولید می‌کند. توسعه‌دهنده باید هنگام تغییر وضعیت کامپوننت، متدهای مربوطه LifecycleRegistry را به صورت دستی فراخوانی کند.

مثال پیاده‌سازی LifecycleOwner در Custom View:

kotlin
class MyCustomView(
    context: Context,
    attrs: AttributeSet?
) : FrameLayout(context, attrs), LifecycleOwner {

    private val lifecycleRegistry = LifecycleRegistry(this)

    override val lifecycle: Lifecycle
        get() = lifecycleRegistry

    fun onStart() {
        lifecycleRegistry.setCurrentState(Lifecycle.State.STARTED)
    }

    fun onStop() {
        lifecycleRegistry.setCurrentState(Lifecycle.State.CREATED)
    }
}

در این مثال LifecycleRegistry به عنوان ذخیره‌ساز وضعیت عمل می‌کند. متدهای onStart/onStop باید توسط کامپوننت والد (مثلاً Activity) هنگامی که Custom View قابل مشاهده یا پنهان می‌شود فراخوانی شوند. LifecycleRegistry به طور خودکار رویدادهای لازم برای انتقال بین وضعیت‌ها را محاسبه می‌کند و همه Observer‌های مشترک را مطلع می‌کند.

در پیاده‌سازی LifecycleOwner سفارشی، رعایت این قانون مهم است: وضعیت LifecycleRegistry باید در متد مربوطه چرخه حیات، پس از همه عملیات‌های دیگر، آخرین به‌روزرسانی شود. این تضمین می‌کند که Observer‌ها زمانی که کامپوننت کاملاً برای وضعیت جدید آماده است، اعلان دریافت کنند. استفاده از LifecycleRegistry.createUnsafe به عنوان جایگزین نیز ممکن است، اما نیاز به احتیاط با نخ‌ها دارد.

LifecycleOwner در کامپوننت‌های Jetpack

LifecycleOwner پایه‌ای برای چندین کامپوننت کلیدی Android Jetpack است. LiveData از LifecycleOwner برای تعیین وضعیت فعال و لغو اشتراک خودکار هنگام نابودی کامپوننت استفاده می‌کند. ViewModel مستقیماً LifecycleOwner را پیاده‌سازی نمی‌کند، اما می‌تواند از طریق SavedStateHandle Lifecycle دریافت کند. Navigation Component از LifecycleOwner برای مدیریت اشتراک‌ها در NavBackStackEntry استفاده می‌کند. درک این ارتباط به ساخت معماری برنامه بر پایه‌ای محکم کمک می‌کند.

تعامل LiveData با LifecycleOwner:

kotlin
class ExampleActivity : AppCompatActivity() {
    private val viewModel: ExampleViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewModel.userData.observe(this) { data ->
            // this — LifecycleOwner (Activity)
            // کد فقط زمانی اجرا می‌شود که Activity در وضعیت RESUMED است
            updateUI(data)
        }
    }
}

LiveData در متد observe() به LifecycleOwner نیاز دارد، زیرا این تضمین می‌کند که به‌روزرسانی‌های UI فقط در وضعیت فعال رخ می‌دهند. اگر Activity در پس‌زمینه باشد، LiveData آخرین مقدار را حفظ می‌کند اما Observer را مطلع نمی‌کند. هنگام بازگشت به RESUMED، Observer بدون درخواست اضافی به شبکه یا پایگاه داده، مقدار فعلی را دریافت می‌کند.

DataBinding نیز از LifecycleOwner برای اتصال فیلدهای observable به چرخه حیات Activity یا Fragment استفاده می‌کند. این از نشت حافظه در ترکیب ViewModel + DataBinding جلوگیری می‌کند — همه اشتراک‌ها هنگام نابودی LifecycleOwner به طور خودکار پاک می‌شوند. این رویکرد کد را اعلانی و ایمن می‌کند.

توصیه‌های استفاده

استفاده صحیح از LifecycleOwner نیاز به رعایت چند قانون کلیدی دارد. اولین و مهم‌ترین: همیشه Observer را در onCreate/onViewCreated مشترک کنید، نه دیرتر. این تضمین می‌کند که Observer وضعیت اولیه Lifecycle (CREATED پس از onCreate) را دریافت می‌کند و رویدادها را از دست نمی‌دهد. قانون دوم: از DefaultLifecycleObserver به جای رویکرد حاشیه‌نویسی برای همه پروژه‌های جدید استفاده کنید.

  • ارجاع به LifecycleOwner را در فیلدهای ایستا یا singletonها ذخیره نکنید — این منجر به نشت کل Activity می‌شود
  • وضعیت Lifecycle را از طریق getCurrentState() قبل از انجام عملیات حساس به وضعیت بررسی کنید
  • Observer را در داخل لامبدا ایجاد نکنید — هر بازترکیب یک شیء جدید ایجاد می‌کند و Observerهای قدیمی به طور خودکار لغو اشتراک نمی‌شوند
  • برای کروتین‌ها از repeatOnLifecycle استفاده کنید — بلوک با ورود به وضعیت مشخص شده اجرا می‌شود و با خروج از آن لغو می‌شود
  • setCurrentState را در LifecycleRegistry از نخ پس‌زمینه فراخوانی نکنید — این تضمین‌های تک‌نخی چرخه حیات را نقض می‌کند

رویکرد مدرن برای کار با کروتین‌ها و LifecycleOwner — افزونه repeatOnLifecycle:

kotlin
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.flow.collect { value ->
            updateUI(value)
        }
    }
}

این الگو تضمین می‌کند که collect روی Flow فقط در وضعیت STARTED یا RESUMED فعال است. هنگام انتقال به STOPPED، جمع‌آوری به طور خودکار لغو می‌شود و هنگام بازگشت به STARTED، دوباره راه‌اندازی می‌شود. repeatOnLifecycle جایگزین لغو اشتراک دستی از Flow در Fragment می‌شود و رویکرد توصیه‌شده Google برای کار با جریان‌های داده ناهمزمان در کامپوننت‌های UI است.

یک توصیه مهم دیگر: از LifecycleObserver برای منطق غیرمرتبط با چرخه حیات سوءاستفاده نکنید. اگر کامپوننت باید در وضعیت خاصی عملی انجام دهد اما هنگام نابودی نیاز به لغو اشتراک ندارد، بهتر است از فراخوانی صریح متدها در onStart/onStop استفاده کنید. LifecycleObserver برای کامپوننت‌های طولانی‌مدت (LocationListener, SensorManager) توجیه‌پذیر است، جایی که مدیریت دستی اشتراک‌ها پیچیده و مستعد خطا است.

سوالات متداول

LifecycleOwner چه تفاوتی با Lifecycle دارد؟

LifecycleOwner — یک رابط است که اعلام می‌کند یک شیء چرخه حیات دارد. Lifecycle — کلاسی است که وضعیت فعلی را ذخیره می‌کند و Observer را مدیریت می‌کند. LifecycleOwner از طریق getLifecycle() Lifecycle را فراهم می‌کند.

آیا باید LifecycleObserver را به صورت دستی لغو اشتراک کرد؟

خیر، Lifecycle هنگام انتقال به DESTROYED به طور خودکار همه Observer‌ها را لغو اشتراک می‌کند. این یکی از مزایای اصلی LifecycleOwner است — توسعه‌دهنده نیازی به فراخوانی دستی removeObserver در onDestroy ندارد.

LifecycleOwner در Fragment چگونه کار می‌کند؟

Fragment LifecycleOwner را از طریق رابط فرگمنت‌های AndroidX پیاده‌سازی می‌کند. Lifecycle آن به چرخه حیات Fragment به طور جداگانه از Activity متصل است. این به Observer اجازه می‌دهد به رویدادهای Fragment واکنش نشان دهد، نه Activity والد.

آیا می‌توان LifecycleOwner را در Custom View پیاده‌سازی کرد؟

بله، برای این کار از LifecycleRegistry استفاده می‌شود. Custom View باید رابط LifecycleOwner را پیاده‌سازی کند و به صورت دستی وضعیت LifecycleRegistry را هنگام تغییر دید یا اتصال به پنجره به‌روزرسانی کند.

اگر CoroutineScope وجود دارد، چرا LifecycleOwner لازم است؟

LifecycleOwner وظیفه دیگری را حل می‌کند: مدیریت اشتراک‌های رویدادهای چرخه حیات، نه لغو کروتین‌ها. برای کروتین‌ها از lifecycleScope استفاده می‌شود که کروتین‌های راه‌اندازی شده را هنگام نابودی LifecycleOwner به طور خودکار لغو می‌کند.

خلاصه

  • LifecycleOwner — رابط Android Jetpack برای دسترسی به چرخه حیات از طریق getLifecycle()
  • به طور پیش‌فرض در AppCompatActivity و Fragment از AndroidX پیاده‌سازی شده است
  • از DefaultLifecycleObserver پشتیبانی می‌کند — روش اشتراک مدرن و ایمن از نظر نوع
  • هنگام انتقال به DESTROYED به طور خودکار Observer را لغو اشتراک می‌کند و از نشت حافظه جلوگیری می‌کند
  • در LiveData، DataBinding و Navigation Component به عنوان پایه lifecycle-aware استفاده می‌شود
  • از طریق LifecycleRegistry امکان ایجاد LifecycleOwner سفارشی برای Custom Views و Services را فراهم می‌کند
  • جایگزین مدرن — repeatOnLifecycle برای کروتین‌ها و Flow که جایگزین اشتراک دستی می‌شود

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید