إدخال المهام التابعة باستخدام Hilt

‫Hilt هي مكتبة لتوفير التبعيات في Android، وهي تقلّل من الرمز النموذجي اللازم لتوفير التبعيات يدويًا في مشروعك. يتطلّب إجراء إدخال التبعيات يدويًا إنشاء كل فئة وتبعياتها يدويًا، واستخدام الحاويات لإعادة استخدام التبعيات وإدارتها.

توفّر Hilt طريقة عادية لاستخدام ميزة "توفير التبعية" في تطبيقك من خلال توفير حاويات لكل فئة Android في مشروعك وإدارة مراحل نشاطها تلقائيًا. تم إنشاء Hilt استنادًا إلى مكتبة DI الشائعة Dagger للاستفادة من الصحة في وقت الترجمة والأداء في وقت التشغيل وقابلية التوسّع وتوافقها مع "استوديو Android" التي توفّرها Dagger. لمزيد من المعلومات، يُرجى الاطّلاع على Hilt وDagger.

يشرح هذا الدليل المفاهيم الأساسية لـ Hilt والحاويات التي يتم إنشاؤها. ويتضمّن أيضًا عرضًا توضيحيًا لكيفية إعداد تطبيق حالي لاستخدام Hilt.

إضافة التبعيات

أولاً، أضِف المكوّن الإضافي hilt-android-gradle-plugin إلى ملف build.gradle الجذر الخاص بمشروعك:

Kotlin

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:

Kotlin

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:

Kotlin

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، لست بحاجة إلى إضافة تعليقات توضيحية إلى عناصر فردية قابلة للإنشاء. بدلاً من ذلك، أضِف تعليقًا توضيحيًا إلى ComponentActivity الجذر باستخدام @AndroidEntryPoint. ويعمل ذلك كنقطة دخول واحدة لتوفير التبعية في التسلسل الهرمي لواجهة المستخدم بالكامل، ما يتيح لك الوصول إلى ViewModels التي تم إدخالها باستخدام Hilt مباشرةً من داخل الدوال القابلة للإنشاء.

تنشئ السمة @AndroidEntryPoint أحد مكونات Hilt لكل فئة Android في مشروعك. يمكن أن تتلقّى هذه المكوّنات عناصر تابعة من فئاتها الرئيسية، كما هو موضّح في التسلسل الهرمي للمكوّنات.

للحصول على الاعتماديات من أحد المكوّنات، استخدِم علامة التوضيح @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 واجهة، لا يمكنك إدخالها باستخدام طريقة وضع التصميم. بدلاً من ذلك، قدِّم إلى Hilt معلومات الربط من خلال إنشاء دالة مجرّدة مزوّدة بالتعليق التوضيحي @Binds داخل وحدة 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
}

يتم وضع التعليق التوضيحي AnalyticsModule على وحدة Hilt @InstallIn(ActivityComponent.class)لأنّك تريد أن يدرج Hilt هذه الاعتمادية في ExampleActivity. تعني هذه التعليقات التوضيحية أنّ جميع التبعيات في AnalyticsModule متاحة في جميع أنشطة التطبيق.

توفير مثيلات باستخدام ‎ @Provides

الواجهات ليست الحالة الوحيدة التي لا يمكنك فيها إدخال نوع من خلال الدالة الإنشائية. لا يمكن أيضًا استخدام ميزة "إدخال البيانات عبر الدالة الإنشائية" إذا لم تكن تملك الفئة لأنّها تأتي من مكتبة خارجية (مثل فئات Retrofit أو OkHttpClient أو قواعد بيانات Room)، أو إذا كان يجب إنشاء مثيلات باستخدام نمط الإنشاء.

لنأخذ المثال السابق. إذا لم تكن تملك فئة AnalyticsService بشكل مباشر، يمكنك إخبار Hilt بكيفية توفير مثيلات من هذا النوع من خلال إنشاء دالة داخل وحدة Hilt وإضافة التعليق التوضيحي @Provides إلى تلك الدالة.

توفّر الدالة التي تمّت إضافة التعليقات التوضيحية إليها المعلومات التالية إلى 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

في المثال، إذا حدّدت نطاق AnalyticsAdapter إلى ActivityComponent باستخدام @ActivityScoped، يوفّر 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، يمكنك الاطّلاع على مقالة تحديد النطاق في Android وHilt.

التدرّج الهرمي للمكوّنات

يسمح تثبيت وحدة في أحد المكوّنات بالوصول إلى عمليات الربط الخاصة بها كاعتمادية لعمليات الربط الأخرى في هذا المكوّن أو في أي مكوّن ثانوي أسفله في التسلسل الهرمي للمكوّنات.

‫ActivityComponent ضِمن
    ActivityRetainedComponent يقع ViewModelComponent ضمن
    ActivityRetainedComponent. ‫ActivityRetainedComponent وServiceComponent
    ضِمن SingletonComponent.
الشكل 1. التسلسل الهرمي للمكوّنات التي ينشئها 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() داخل الدالة المركّبة للوصول إلى ViewModel. على الرغم من أنّ Hilt يتيح استخدام معظم فئات Android الشائعة، قد تظل تواجه فئات غير متوافقة تحتاج فيها إلى تنفيذ عملية الحقن المباشر في المتغيرات.

في هذه الحالات، يمكنك إنشاء نقطة دخول باستخدام التعليق التوضيحي @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، يُرجى الاطّلاع على المراجع الإضافية التالية.

نماذج

المدوّنات

عرض المحتوى