---
title: شنونده‌ها
description: با اصول اولیه شنونده‌ها توی ReArch آشنا شو.
---

# شنونده‌ها
توی ReArch دو نوع شنونده داریم:  
1. شنونده‌های موقتی که وقتی دیگه نیازی بهشون نیست به‌صورت دستی حذف می‌شن  
2. شنونده‌هایی که تا وقتی خود کانتینر زنده‌ست، زنده می‌مونن (مثلاً برای یه لاگر)  

نوع اول شنونده از طریق متد `listen` که روی کانتینرها وجود داره مدیریت می‌شه،  
و توی [کانتینرها](/core/containers) توضیح داده شده.  
نوع دوم چیزیه که این صفحه بهش می‌پردازه.

برای پیاده‌سازی یه شنونده بلندمدت،  
فقط کافیه یه کپسول جدید بسازی (با یه تغییر کوچیک—ادامه رو بخون)!  
اولین تلاشت (که *اشتباهه*) ممکنه چیزی شبیه این باشه:

```dart
/// یه کپسول شنونده که به یه سری کپسول دیگه گوش می‌ده.  
/// توجه کن به نوع بازگشتی `void`؛  
/// شنونده‌ها فقط به داده‌های دیگه گوش می‌دن و چیزی برنمی‌گردونن.  
/// هشدار: این (یه کم) اشتباهه! برای اطلاعات بیشتر ادامه رو بخون.  
void myListener(CapsuleHandle use) {
  print(use(foobarCapsule));
}

// توی تابع main() یا یه جای مشابه،  
// شنونده رو مقداردهی کن (که یه بار صداش می‌کنه):  
container.read(myListener);                                    // فقط دارت  
CapsuleContainerProvider.containerOf(context).read(myListener) // فلاتر
```

اما کد بالا *اون‌طور که انتظار داری کار نمی‌کنه*؛  
شنونده یه بار فراخوانی می‌شه،  
ولی دیگه هیچ‌وقت دوباره فراخوانی نمی‌شه.  
داره چی می‌گذره؟

نکته کلیدی اینجاست که `myListener` از یه اثر جانبی (`print()`) استفاده می‌کنه  
که ReArch ازش خبر نداره چون از طریق یه اثر `use.xyz` ثبت نشده.  
داخلاً، ReArch یادش می‌مونه که کدوم کپسول‌ها از اثرات جانبی استفاده می‌کنن و از این اطلاعات برای فعال کردن  
بهینه‌سازی‌های مهمی استفاده می‌کنه، به‌خصوص _جمع‌آوری زباله ایدمپوتنت (idempotent garbage collection)_.  
به‌طور خلاصه، توی مثال بالا،  
وقتی `foobarCapsule` داده جدید منتشر می‌کنه،  
`myListener` به‌صورت خودکار حذف می‌شه (به‌جای اینکه بازسازی بشه) چون هیچ _تقاضایی_ نداره.  
یه کپسول وقتی تقاضا داره که خودش یا یکی از وابسته‌هاش یه اثر جانبی ثبت کنه  
(که شامل گوش دادن توسط یه ویجت که بخشی از UI هست هم می‌شه).

پس راه‌حل اینجا ساده‌ست: چون توی `myListener` از یه اثر جانبی استفاده می‌کنیم  
که ReArch ازش خبر نداره، بیایم به ReArch بگیم که داریم از یه اثر جانبی استفاده می‌کنیم!  
می‌تونی هر اثر جانبی تصادفی‌ای رو ثبت کنی،  
ولی یه اثر جانبی no-op داخلی وجود داره که یه کپسول رو به‌عنوان شنونده اعلام می‌کنه  
(و چون یه اثر جانبیه، جمع‌آوری زباله رو غیرفعال می‌کنه).

```dart
/// نسخه اصلاح‌شده شنونده که یه اثر جانبی ثبت می‌کنه  
/// تا به‌صورت خودکار حذف نشه.  
void myListener(CapsuleHandle use) {
  use.asListener();
  print(use(foobarCapsule));
}

// و در نهایت شنونده رو یه جایی نزدیک شروع اپلیکیشنت مقداردهی کن.  
container.read(myListener);                                    // فقط دارت  
CapsuleContainerProvider.containerOf(context).read(myListener) // فلاتر
```

<Info>
`CapsuleContainerProvider.containerOf()` یه متد خاص فلاتره که  
کانتینر اپلیکیشن در حال اجرا رو می‌گیره.  
استفاده از این تابع برای مقداردهی شنونده‌ها اشکالی نداره، ولی برای _تقریباً_ هیچ چیز دیگه‌ای نباید استفاده بشه.  
(همچنین به‌عنوان یه راه فرار برای وقتی که با یه سری API خارجی کار می‌کنی  
که با واکنش‌پذیری ReArch خوب بازی نمی‌کنن عمل می‌کنه.)

از اونجایی که استفاده از `CapsuleContainerProvider.containerOf` توی تقریباً همه موقعیت‌ها توصیه نمی‌شه،  
می‌تونی با روش زیر هم شنونده‌ها رو مقداردهی کنی:  
```dart
class InitializeListeners extends RearchConsumer {
  const InitializeListeners({required this.child, super.key});

  final Widget child;
  
  Widget build(BuildContext context, WidgetHandle use) {
    use(myListener);
    return child;
  }
}
```  
و یه ویجت `InitializeListeners` درست زیر `RearchBootstrapper` بندازی.  
اگه به کد اعلانی (declarative) خیلی مقیدی، این یه روش جایگزین براته  
که اپلیکیشنت رو به‌صورت اعلانی مقداردهی کنی  
و از استفاده از `CapsuleContainerProvider.containerOf()` پرهیز کنی.
</Info>
