تزریق وابستگی با Hilt

Hilt یک کتابخانه تزریق وابستگی برای Android است که کد تکراری تزریق وابستگی دستی را در پروژه شما کاهش می‌دهد. برای انجام تزریق وابستگی دستی، باید هر کلاس و وابستگی‌های آن را به‌صورت دستی بسازید و از محفظه‌ها برای استفاده مجدد و مدیریت وابستگی‌ها استفاده کنید.

Hilt با ارائه محفظه‌هایی برای هر کلاس Android در پروژه شما و مدیریت خودکار چرخه‌های حیات آن‌ها، روشی استاندارد برای استفاده از تزریق وابستگی در برنامه‌تان ارائه می‌دهد. Hilt بر روی کتابخانه محبوب DI Dagger ساخته شده است تا از صحت زمان ترجمه، عملکرد زمان اجرا، مقیاس‌پذیری، و پشتیبانی Android Studio که Dagger ارائه می‌دهد بهره‌مند شود. برای اطلاعات بیشتر، Hilt و Dagger را ببینید.

این راهنما مفاهیم پایه Hilt و محفظه‌های تولیدشده آن را توضیح می‌دهد. همچنین نمونه‌ای از نحوه راه‌اندازی برنامه موجود برای استفاده از Hilt را شامل می‌شود.

درحال افزودن وابستگی‌ها

ابتدا افزونه hilt-android-gradle-plugin را به فایل ریشه build.gradle پروژه‌تان اضافه کنید:

کاتلین

plugins {
  ...
  id("com.google.dagger.hilt.android") version "2.57.1" apply false
}

شیک

plugins {
  ...
  id 'com.google.dagger.hilt.android' version '2.57.1' apply false
}

سپس، افزونه Gradle را اعمال کنید و این وابستگی‌ها را در فایل app/build.gradle خود اضافه کنید:

کاتلین

plugins {
  id("com.google.devtools.ksp")
  id("com.google.dagger.hilt.android")
}

android {
  ...
}

dependencies {
  implementation("com.google.dagger:hilt-android:2.57.1")
  ksp("com.google.dagger:hilt-android-compiler:2.57.1")
}

شیک

...
plugins {
  id 'com.google.devtools.ksp'
  id 'com.google.dagger.hilt.android'
}

android {
  ...
}

dependencies {
  implementation "com.google.dagger:hilt-android:2.57.1"
  ksp "com.google.dagger:hilt-compiler:2.57.1"
}

برای اطمینان از اینکه پروژه‌تان برای Java 17 پیکربندی شده است (که برای نسخه‌های Jetpack Compose و Hilt لازم است)، موارد زیر را به فایل app/build.gradle اضافه کنید:

کاتلین

android {
  ...
  compileOptions {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
  }
}

شیک

android {
  ...
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_17
    targetCompatibility JavaVersion.VERSION_17
  }
}

کلاس برنامه Hilt

همه برنامه‌هایی که از Hilt استفاده می‌کنند باید حاوی کلاس Application باشند که با @HiltAndroidApp حاشیه‌نویسی شده است.

@HiltAndroidApp تولید کد Hilt را راه‌اندازی می‌کند، ازجمله کلاس پایه برای برنامه شما که به‌عنوان محفظه وابستگی سطح برنامه عمل می‌کند.

@HiltAndroidApp
class ExampleApplication : Application() { ... }

این مؤلفه Hilt تولیدشده به چرخه حیات شیء Application متصل است و وابستگی‌هایی را برای آن فراهم می‌کند. علاوه‌براین، این مؤلفه والد برنامه است، به این معنی که سایر مؤلفه‌ها می‌توانند به وابستگی‌هایی که ارائه می‌دهد دسترسی داشته باشند.

تزریق وابستگی‌ها به کلاس‌های Android

وقتی Hilt در کلاس Application شما راه‌اندازی شد و مؤلفه سطح برنامه دردسترس بود، Hilt می‌تواند وابستگی‌ها را برای کلاس‌های Android دیگری که حاشیه‌نویسی @AndroidEntryPoint دارند فراهم کند:

@AndroidEntryPoint
class ExampleActivity : ComponentActivity() { ... }

Hilt درحال‌حاضر از کلاس‌های Android زیر پشتیبانی می‌کند:

  • ‫Application (بااستفاده از @HiltAndroidApp)
  • ‫ViewModel (بااستفاده از @HiltViewModel)
  • Activity
  • Service
  • BroadcastReceiver

در Compose، لازم نیست composable-های تکی را حاشیه‌نویسی کنید. درعوض، ComponentActivity ریشه را با @AndroidEntryPoint حاشیه‌نویسی کنید. این به‌عنوان نقطه ورودی DI واحد برای کل سلسله‌مراتب واسط کاربر شما عمل می‌کند، بنابراین می‌توانید مستقیماً در توابع ترکیب‌پذیر خود به ViewModels تزریق‌شده توسط Hilt دسترسی داشته باشید.

@AndroidEntryPoint برای هر کلاس Android در پروژه شما یک مؤلفه Hilt جداگانه تولید می‌کند. این مؤلفه‌ها می‌توانند وابستگی‌ها را از کلاس‌های والد مربوطه خود دریافت کنند، همان‌طور که در سلسله‌مراتب مؤلفه توضیح داده شده است.

برای دریافت وابستگی‌ها از مؤلفه، از یادداشت @Inject برای انجام تزریق فیلد استفاده کنید:

@AndroidEntryPoint
class ExampleActivity : ComponentActivity() {

  @Inject lateinit var analytics: AnalyticsAdapter
  ...
}

کلاس‌هایی که Hilt تزریق می‌کند می‌توانند کلاس‌های پایه دیگری داشته باشند که آن‌ها هم از تزریق استفاده می‌کنند. اگر این کلاس‌ها انتزاعی باشند، به حاشیه‌نویسی @AndroidEntryPoint نیاز ندارند.

برای کسب اطلاعات بیشتر درباره اینکه کلاس Android در کدام فراخوانی چرخه حیات تزریق می‌شود، طول عمر مؤلفه را ببینید.

تعریف کردن اتصال‌های Hilt

برای انجام تزریق فیلد، Hilt باید بداند چگونه نمونه‌هایی از وابستگی‌های لازم را از مؤلفه مربوطه ارائه دهد. اتصال حاوی اطلاعات لازم برای ارائه نمونه‌های یک نوع به‌عنوان وابستگی است.

یک روش برای ارائه اطلاعات اتصال به Hilt، تزریق سازنده است. از حاشیه‌نویسی @Inject در سازنده کلاس استفاده کنید تا به Hilt بگویید چگونه نمونه‌های آن کلاس را ارائه دهد:

class AnalyticsAdapter @Inject constructor(
  private val service: AnalyticsService
) { ... }

پارامترهای سازنده حاشیه‌نویسی‌شده یک کلاس، وابستگی‌های آن کلاس هستند. در این مثال، AnalyticsAdapter دارای AnalyticsService به‌عنوان وابستگی است. بنابراین، Hilt باید بداند که چگونه نمونه‌های AnalyticsService را ارائه دهد.

پیمانه‌های Hilt

گاهی‌اوقات نمی‌توان نوعی را تزریق سازنده کرد. این اتفاق می‌تواند به دلایل متعددی رخ دهد. برای مثال، نمی‌توانید میانایی را تزریق سازنده کنید. همچنین نمی‌توانید نوعی را که مالک آن نیستید، مانند کلاسی از یک کتابخانه خارجی، تزریق سازنده کنید. در این موارد، می‌توانید بااستفاده از مدول‌های Hilt، اطلاعات اتصال را به Hilt ارائه دهید.

یک ماژول Hilt کلاسی است که با @Module حاشیه‌نویسی شده است. این دستورالعمل‌ها را درباره نحوه ایجاد نمونه‌هایی از انواع که نمی‌توانند ازطریق تزریق سازنده ارائه شوند، مانند میانجی‌ها یا کلاس‌های شخص ثالث، به Hilt ارائه می‌دهد. همچنین باید هر پیمانه را با @InstallIn حاشیه‌نویسی کنید تا به Hilt بگویید هر پیمانه در کدام کلاس Android استفاده یا نصب خواهد شد.

وابستگی‌هایی که در پیمانه‌های Hilt ارائه می‌دهید در همه مؤلفه‌های تولیدشده که با کلاس Android مرتبط هستند و پیمانه Hilt را در آن نصب می‌کنید دردسترس هستند.

تزریق نمونه‌های میانای با @Binds

مثال AnalyticsService را درنظر بگیرید. اگر AnalyticsService یک میانای کاربری باشد، نمی‌توانید آن را تزریق سازنده کنید. درعوض، با ایجاد یک تابع انتزاعی حاشیه‌نویسی‌شده با @Binds در داخل یک ماژول Hilt، اطلاعات اتصال را به Hilt ارائه دهید.

حاشیه‌نویسی @Binds به Hilt می‌گوید که وقتی نیاز به ارائه نمونه‌ای از میانای کاربری دارد، از کدام پیاده‌سازی استفاده کند.

تابع حاشیه‌نویسی‌شده اطلاعات زیر را به Hilt ارائه می‌دهد:

  • نوع پاسخ تابع به Hilt می‌گوید که تابع نمونه‌های کدام میانای را ارائه می‌دهد.
  • پارامتر تابع به Hilt می‌گوید کدام پیاده‌سازی را ارائه دهد.
interface AnalyticsService {
  fun analyticsMethods()
}

// Constructor-injected, because Hilt needs to know how to
// provide instances of AnalyticsServiceImpl, too.
class AnalyticsServiceImpl @Inject constructor(
  ...
) : AnalyticsService { ... }

@Module
@InstallIn(ActivityComponent::class)
abstract class AnalyticsModule {

  @Binds
  abstract fun bindAnalyticsService(
    analyticsServiceImpl: AnalyticsServiceImpl
  ): AnalyticsService
}

ماژول Hilt AnalyticsModule با @InstallIn(ActivityComponent.class) حاشیه‌نویسی شده است زیرا می‌خواهید Hilt آن وابستگی را به ExampleActivity تزریق کند. این حاشیه‌نویسی یعنی همه وابستگی‌ها در AnalyticsModule در همه فعالیت‌های برنامه دردسترس است.

تزریق نمونه‌ها با ‎ @Provides

رابط‌ها تنها موردی نیستند که نمی‌توانید نوعی را تزریق سازنده کنید. اگر مالک کلاس نباشید، تزریق سازنده نیز امکان‌پذیر نیست زیرا از یک کتابخانه خارجی می‌آید (کلاس‌هایی مانند Retrofit، OkHttpClient، یا پایگاه‌های داده Room)، یا اگر نمونه‌ها باید با الگوی سازنده ایجاد شوند.

مثال قبلی را درنظر بگیرید. اگر مستقیماً مالک کلاس AnalyticsService نیستید، می‌توانید با ایجاد تابعی در ماژول Hilt و حاشیه‌نویسی آن تابع با @Provides، به Hilt بگویید چگونه نمونه‌هایی از این نوع را ارائه دهد.

تابع حاشیه‌نویسی‌شده اطلاعات زیر را به Hilt ارائه می‌دهد:

  • نوع پاسخ تابع به Hilt می‌گوید که تابع نمونه‌های چه نوعی را ارائه می‌دهد.
  • پارامترهای تابع وابستگی‌های نوع مربوطه را به Hilt می‌گویند.
  • بدنه تابع به Hilt می‌گوید که چگونه نمونه‌ای از نوع مربوطه را ارائه دهد. Hilt هر بار که لازم باشد نمونه‌ای از آن نوع را ارائه دهد، بدنه تابع را اجرا می‌کند.
@Module
@InstallIn(ActivityComponent::class)
object AnalyticsModule {

  @Provides
  fun provideAnalyticsService(
    // Potential dependencies of this type
  ): AnalyticsService {
      return Retrofit.Builder()
               .baseUrl("https://example.com")
               .build()
               .create(AnalyticsService::class.java)
  }
}

ارائه چندین اتصال برای یک نوع

در مواردی که نیاز دارید Hilt پیاده‌سازی‌های مختلفی از یک نوع را به‌عنوان وابستگی ارائه دهد، باید چندین اتصال به Hilt ارائه دهید. می‌توانید بااستفاده از توصیف‌کننده‌ها، چندین اتصال را برای یک نوع تعریف کنید.

توصیف‌کننده حاشیه‌نویسی‌ای است که از آن برای شناسایی اتصال خاصی برای یک نوع استفاده می‌کنید، وقتی که برای آن نوع چندین اتصال تعریف شده باشد.

مثال را درنظر بگیرید. اگر لازم است تماس‌های AnalyticsService را رهگیری کنید، می‌توانید از شیء OkHttpClient با رهگیر استفاده کنید. برای سرویس‌های دیگر، ممکن است لازم باشد تماس‌ها را به روش دیگری رهگیری کنید. در این صورت، باید به Hilt بگویید که چگونه دو پیاده‌سازی متفاوت از OkHttpClient ارائه دهد.

ابتدا، توصیف‌کننده‌هایی را که برای حاشیه‌نویسی روش‌های @Binds یا @Provides استفاده خواهید کرد تعریف کنید:

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class AuthInterceptorOkHttpClient

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class OtherInterceptorOkHttpClient

سپس، Hilt باید بداند که چگونه نمونه‌ای از نوعی را که با هر واجدشرایط مطابقت دارد ارائه دهد. در این مورد، می‌توانید از یک ماژول Hilt با @Provides استفاده کنید. هر دو روش نوع پاسخ یکسانی دارند، اما واجدشرایط‌کننده‌ها آن‌ها را به‌عنوان دو اتصال متفاوت برچسب‌گذاری می‌کنند:

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

  @AuthInterceptorOkHttpClient
  @Provides
  fun provideAuthInterceptorOkHttpClient(
    authInterceptor: AuthInterceptor
  ): OkHttpClient {
      return OkHttpClient.Builder()
               .addInterceptor(authInterceptor)
               .build()
  }

  @OtherInterceptorOkHttpClient
  @Provides
  fun provideOtherInterceptorOkHttpClient(
    otherInterceptor: OtherInterceptor
  ): OkHttpClient {
      return OkHttpClient.Builder()
               .addInterceptor(otherInterceptor)
               .build()
  }
}

می‌توانید نوع خاصی را که نیاز دارید با حاشیه‌نویسی فیلد یا پارامتر با واجدشرایط مربوطه تزریق کنید:

// As a dependency of another class.
@Module
@InstallIn(ActivityComponent::class)
object AnalyticsModule {

  @Provides
  fun provideAnalyticsService(
    @AuthInterceptorOkHttpClient okHttpClient: OkHttpClient
  ): AnalyticsService {
      return Retrofit.Builder()
               .baseUrl("https://example.com")
               .client(okHttpClient)
               .build()
               .create(AnalyticsService::class.java)
  }
}

// As a dependency of a constructor-injected class.
class ExampleServiceImpl @Inject constructor(
  @AuthInterceptorOkHttpClient private val okHttpClient: OkHttpClient
) : ...

// At field injection.
@AndroidEntryPoint
class ExampleActivity: ComponentActivity() {

  @AuthInterceptorOkHttpClient
  @Inject lateinit var okHttpClient: OkHttpClient
}

به‌عنوان یک روال مطلوب، اگر توصیف‌کننده‌ای را به نوعی اضافه می‌کنید، توصیف‌کننده‌ها را به همه روش‌های ممکن برای ارائه آن وابستگی اضافه کنید. رها کردن پیاده‌سازی پایه یا مشترک بدون واجدشرایط‌کننده مستعد خطا است و می‌تواند منجر به تزریق وابستگی اشتباه توسط Hilt شود.

توصیف‌گرهای ازپیش تعریف‌شده در Hilt

Hilt برخی‌از واجدشرایط‌های ازپیش تعریف‌شده را ارائه می‌دهد. برای مثال، ازآنجایی‌که ممکن است به کلاس Context از برنامه یا فعالیت نیاز داشته باشید، Hilt اصلاح‌کننده‌های @ApplicationContext و @ActivityContext را ارائه می‌دهد.

فرض کنید کلاس AnalyticsAdapter از مثال به بافت فعالیت نیاز دارد. کد زیر نشان می‌دهد که چگونه بافت فعالیت را به AnalyticsAdapter ارائه دهید:

class AnalyticsAdapter @Inject constructor(
    @ActivityContext private val context: Context,
    private val service: AnalyticsService
) { ... }

برای سایر اتصال‌های ازپیش تعریف‌شده موجود در Hilt، به اتصال‌های پیش‌فرض مؤلفه مراجعه کنید.

مؤلفه‌های تولیدشده برای کلاس‌های Android

برای هر کلاس Android که می‌توانید تزریق فیلد را در آن انجام دهید، یک مؤلفه Hilt مرتبط وجود دارد که می‌توانید در حاشیه‌نویسی @InstallIn به آن ارجاع دهید. هر مؤلفه Hilt مسئول تزریق اتصال‌های خود به کلاس Android مربوطه است.

نمونه‌های قبلی استفاده از ActivityComponent را در پیمانه‌های Hilt نشان دادند.

Hilt مؤلفه‌های زیر را ارائه می‌دهد:

مؤلفه Hilt تزریق‌کننده برای
SingletonComponent Application
ActivityRetainedComponent موجود نیست
ViewModelComponent ViewModel
ActivityComponent Activity
ServiceComponent Service

طول عمر مؤلفه

Hilt به‌طور خودکار نمونه‌هایی از کلاس‌های مؤلفه تولیدشده را ایجاد و تخریب می‌کند و چرخه حیات کلاس‌های Android مربوطه را دنبال می‌کند.

عنصر تولیدشده ایجادشده در تاریخ زمان تخریب:
SingletonComponent Application#onCreate() Application نابود شد
ActivityRetainedComponent Activity#onCreate() Activity#onDestroy()
ViewModelComponent ViewModel ایجاد شد ViewModel نابود شد
ActivityComponent Activity#onCreate() Activity#onDestroy()
ServiceComponent Service#onCreate() Service#onDestroy()

دامنه‌های مؤلفه

به‌طور پیش‌فرض، همه اتصال‌ها در Hilt بدون محدوده هستند. این یعنی هربار که برنامه‌تان درخواست اتصال می‌کند، Hilt نمونه جدیدی از نوع موردنیاز ایجاد می‌کند.

در این مثال، هر بار که Hilt‏ AnalyticsAdapter را به‌عنوان وابستگی به نوع دیگری یا ازطریق تزریق فیلد (مانند ExampleActivity) ارائه می‌دهد، Hilt نمونه جدیدی از AnalyticsAdapter را ارائه می‌دهد.

بااین‌حال، Hilt همچنین اجازه می‌دهد که یک اتصال به یک مؤلفه خاص محدود شود. Hilt فقط یک‌بار برای هر نمونه از مؤلفه‌ای که اتصال به آن محدود شده است، یک اتصال محدود ایجاد می‌کند و همه درخواست‌ها برای آن اتصال، همان نمونه را به اشتراک می‌گذارند.

جدول زیر حاشیه‌نویسی‌های دامنه را برای هر مؤلفه تولیدشده فهرست می‌کند:

کلاس Android عنصر تولیدشده حوزه
Application SingletonComponent @Singleton
Activity ActivityRetainedComponent @ActivityRetainedScoped
ViewModel ViewModelComponent @ViewModelScoped
Activity ActivityComponent @ActivityScoped
Service ServiceComponent @ServiceScoped

در این مثال، اگر بااستفاده از @ActivityScoped، AnalyticsAdapter را به ActivityComponent محدود کنید، Hilt همان نمونه AnalyticsAdapter را درطول عمر فعالیت مربوطه ارائه می‌دهد:

@ActivityScoped
class AnalyticsAdapter @Inject constructor(
  private val service: AnalyticsService
) { ... }

فرض کنید AnalyticsService دارای یک وضعیت داخلی است که نیاز دارد هر بار از همان نمونه استفاده شود—نه تنها در ExampleActivity، بلکه در هر جای دیگری از برنامه. در این حالت، مناسب است که AnalyticsService را به SingletonComponent محدود کنید. نتیجه این است که هرگاه مؤلفه نیاز به ارائه نمونه‌ای از AnalyticsService داشته باشد، هربار همان نمونه را ارائه می‌دهد.

مثال زیر نشان می‌دهد که چگونه می‌توان یک اتصال را به یک مؤلفه در یک ماژول Hilt محدود کرد. محدوده اتصال باید با محدوده مؤلفه‌ای که در آن نصب شده است مطابقت داشته باشد، بنابراین در این مثال باید AnalyticsService را در SingletonComponent به‌جای ActivityComponent نصب کنید:

// If AnalyticsService is an interface.
@Module
@InstallIn(SingletonComponent::class)
abstract class AnalyticsModule {

  @Singleton
  @Binds
  abstract fun bindAnalyticsService(
    analyticsServiceImpl: AnalyticsServiceImpl
  ): AnalyticsService
}

// If you don't own AnalyticsService.
@Module
@InstallIn(SingletonComponent::class)
object AnalyticsModule {

  @Singleton
  @Provides
  fun provideAnalyticsService(): AnalyticsService {
      return Retrofit.Builder()
               .baseUrl("https://example.com")
               .build()
               .create(AnalyticsService::class.java)
  }
}

برای کسب اطلاعات بیشتر درباره دامنه‌های مؤلفه Hilt، به Scoping in Android and Hilt مراجعه کنید.

سلسله مراتب مؤلفه

نصب یک ماژول در یک مؤلفه اجازه می‌دهد تا به پیوندهای آن به‌عنوان وابستگی سایر پیوندها در آن مؤلفه یا در هر مؤلفه فرزند زیر آن در سلسله مراتب مؤلفه دسترسی پیدا کرد.

ActivityComponent is under
    ActivityRetainedComponent. ViewModelComponent is under
    ActivityRetainedComponent. ActivityRetainedComponent و ServiceComponent
    زیر SingletonComponent هستند.
شکل ۱. سلسله‌مراتب مؤلفه‌هایی که Hilt تولید می‌کند.

بست‌های پیش‌فرض مؤلفه

هر مؤلفه Hilt با مجموعه‌ای از اتصال‌های پیش‌فرض ارائه می‌شود که Hilt می‌تواند آن‌ها را به‌عنوان وابستگی به اتصال‌های سفارشی شما تزریق کند. توجه داشته باشید که این اتصال‌ها با نوع فعالیت عمومی مطابقت دارند و نه با هیچ زیرکلاس خاصی. دلیلش این است که Hilt از یک تعریف مؤلفه فعالیت واحد برای تزریق همه فعالیت‌ها استفاده می‌کند. هر فعالیت نمونه متفاوتی از این مؤلفه دارد.

مؤلفه Android اتصال‌های پیش‌فرض
SingletonComponent Application
ActivityRetainedComponent Application
ViewModelComponent SavedStateHandle
ActivityComponent Application، Activity
ServiceComponent Application، Service

اتصال زمینه برنامه نیز بااستفاده از @ApplicationContext دردسترس است. برای مثال:

class AnalyticsServiceImpl @Inject constructor(
  @ApplicationContext context: Context
) : AnalyticsService { ... }

// The Application binding is available without qualifiers.
class AnalyticsServiceImpl @Inject constructor(
  application: Application
) : AnalyticsService { ... }

اتصال بافت فعالیت بااستفاده از @ActivityContext نیز دردسترس است. برای مثال:

class AnalyticsAdapter @Inject constructor(
  @ActivityContext context: Context
) { ... }

// The Activity binding is available without qualifiers.
class AnalyticsAdapter @Inject constructor(
  activity: ComponentActivity
) { ... }

تزریق وابستگی‌ها در کلاس‌هایی که Hilt از آن‌ها پشتیبانی نمی‌کند

در Compose، الگوی استاندارد این است که وابستگی‌ها را بااستفاده از تزریق سازنده به @HiltViewModel تزریق کنید و سپس از hiltViewModel() در داخل composable خود برای دسترسی به ViewModel استفاده کنید. While Hilt supports the most common Android classes, you might still encounter unsupported classes where you need to perform field injection.

در این موارد، می‌توانید بااستفاده از حاشیه‌نویسی @EntryPoint نقطه ورودی ایجاد کنید. نقطه ورود مرز بین کدی است که توسط Hilt مدیریت می‌شود و کدی که مدیریت نمی‌شود. این نقطه‌ای است که کد برای اولین‌بار وارد نمودار اشیایی می‌شود که Hilt مدیریت می‌کند. نقاط ورودی به Hilt اجازه می‌دهند از کدی استفاده کند که Hilt آن را مدیریت نمی‌کند تا وابستگی‌ها را در نمودار وابستگی ارائه دهد.

برای مثال، Hilt مستقیماً از ارائه‌دهندگان محتوا پشتیبانی نمی‌کند. اگر می‌خواهید یک ارائه‌دهنده محتوا از Hilt برای دریافت برخی وابستگی‌ها استفاده کند، باید یک میانای حاشیه‌نویسی‌شده با @EntryPoint برای هر نوع اتصال موردنظرتان تعریف کنید و واجدشرایط‌ها را اضافه کنید. سپس @InstallIn را اضافه کنید تا مؤلفه‌ای را که نقطه ورودی باید در آن نصب شود به‌صورت زیر مشخص کنید:

class ExampleContentProvider : ContentProvider() {

  @EntryPoint
  @InstallIn(SingletonComponent::class)
  interface ExampleContentProviderEntryPoint {
    fun analyticsService(): AnalyticsService
  }

  ...
}

برای دسترسی به نقطه ورودی، از روش ایستا مناسب از EntryPointAccessors استفاده کنید. پارامتر باید نمونه مؤلفه یا شیء @AndroidEntryPoint باشد که به‌عنوان نگهدارنده مؤلفه عمل می‌کند. مطمئن شوید که مؤلفه‌ای که به‌عنوان پارامتر ارسال می‌کنید و روش ثابت EntryPointAccessors هر دو با کلاس Android در حاشیه‌نویسی @InstallIn در رابط @EntryPoint مطابقت داشته باشند:

class ExampleContentProvider: ContentProvider() {
    ...

  override fun query(...): Cursor {
    val appContext = context?.applicationContext ?: throw IllegalStateException()
    val hiltEntryPoint =
      EntryPointAccessors.fromApplication(appContext, ExampleContentProviderEntryPoint::class.java)

    val analyticsService = hiltEntryPoint.analyticsService()
    ...
  }
}

در این مثال، باید از ApplicationContext برای بازیابی نقطه ورودی استفاده کنید زیرا نقطه ورودی در SingletonComponent نصب شده است. اگر اتصالی که می‌خواستید بازیابی کنید در ActivityComponent بود، به‌جای آن از ActivityContext استفاده می‌کردید.

Hilt و Dagger

Hilt کتابخانه توصیه‌شده رسمی برای تزریق وابستگی در Android است. این کتابخانه روشی استاندارد، نظری، و کارآمد برای پیاده‌سازی تزریق وابستگی در برنامه شما ارائه می‌دهد که به‌طور خاص برای Jetpack Compose و معماری‌های تک‌فعالیتی بهینه‌سازی شده است.

اهداف Hilt به‌شرح زیر است:

  • برای ایجاد مجموعه‌ای استاندارد از مؤلفه‌ها و دامنه‌ها برای تسهیل راه‌اندازی، خوانایی، و هم‌رسانی کد بین برنامه‌ها.
  • برای ارائه روشی آسان جهت تأمین اتصال‌های مختلف برای انواع مختلف ساخت، مانند آزمایش، اشکال‌زدایی، یا انتشار.

ازآنجایی‌که سیستم‌عامل Android بسیاری از کلاس‌های چارچوب خود را نمونه‌سازی می‌کند، استفاده از Dagger در برنامه Android مستلزم نوشتن مقدار قابل‌توجهی کد تکراری است. Hilt کد متن استاندارد را که در استفاده از Dagger در برنامه Android دخیل است کاهش می‌دهد. Hilt به‌طور خودکار موارد زیر را تولید و ارائه می‌کند:

  • مؤلفه‌هایی برای ادغام کلاس‌های چارچوب Android با Dagger که درغیراین‌صورت باید به‌صورت دستی ایجاد کنید.
  • حاشیه‌نویسی‌های محدوده برای استفاده با مؤلفه‌هایی که Hilt به‌طور خودکار تولید می‌کند.
  • اتصال‌های ازپیش‌تعریف‌شده برای نمایش کلاس‌های Android مانند Application یا Activity.
  • توصیف‌کننده‌های ازپیش تعریف‌شده برای نشان دادن @ApplicationContext و @ActivityContext.

کد Dagger و Hilt می‌توانند در یک پایگاه کد باهم وجود داشته باشند. بااین‌حال، در اکثر موارد بهتر است از Hilt برای مدیریت همه موارد استفاده از Dagger در Android استفاده کنید. برای انتقال دادن پروژه‌ای که از Dagger به Hilt استفاده می‌کند، راهنمای انتقال را ببینید.

منابع بیشتر

برای کسب اطلاعات بیشتر درباره Hilt، منابع تکمیلی زیر را ببینید.

نمونه‌ها

وبلاگ‌ها

محتوا را مشاهده می‌کند