Hilt هي مكتبة حقن التبعية لنظام Android من شأنها الحد من النص النموذجي. من تنفيذ حقن التبعية اليدوية في مشروعك. تنفيذ التبعية اليدوية حقن الموقع يتطلب منك إنشاء كل فئة وتبعياتها يدويًا، واستخدام الحاويات لإعادة استخدام وإدارة التبعيات.
يوفر Hilt طريقة قياسية لاستخدام DI في تطبيقك من خلال توفير حاويات لكل فئة Android في مشروعك وإدارة مراحل نشاطها تلقائيًا. تم بناء Hilt في أعلى مكتبة DI الشهيرة. يمكنك استخدام Dagger للاستفادة من صحة وقت التجميع وأداء وقت التشغيل وقابلية التوسّع واستوديو Android الدعم التي توفرها أداة Dagger. لمزيد من المعلومات، راجع الاستقلال Dagger.
يشرح هذا الدليل المفاهيم الأساسية لتطبيق Hilt والحاويات التي يتم إنشاؤها. أُنشأها جون هنتر، الذي كان متخصصًا وتشمل أيضًا عرضًا توضيحيًا حول كيفية بدء تشغيل تطبيق حالي لاستخدام Hilt.
إضافة التبعيات
أولاً، أضِف المكوّن الإضافي hilt-android-gradle-plugin
إلى جذر مشروعك.
ملف build.gradle
:
Groovy
plugins { ... id 'com.google.dagger.hilt.android' version '2.44' apply false }
Kotlin
plugins { ... id("com.google.dagger.hilt.android") version "2.44" apply false }
ثم قم بتطبيق المكون الإضافي Gradle وإضافة هذه التبعيات في
ملف app/build.gradle
:
Groovy
... plugins { id 'kotlin-kapt' id 'com.google.dagger.hilt.android' } android { ... } dependencies { implementation "com.google.dagger:hilt-android:2.44" kapt "com.google.dagger:hilt-compiler:2.44" } // Allow references to generated code kapt { correctErrorTypes true }
Kotlin
plugins { id("kotlin-kapt") id("com.google.dagger.hilt.android") } android { ... } dependencies { implementation("com.google.dagger:hilt-android:2.44") kapt("com.google.dagger:hilt-android-compiler:2.44") } // Allow references to generated code kapt { correctErrorTypes = true }
يستخدم Hilt ميزات Java 8. لتفعيل Java 8 في
مشروعك، أضِف ما يلي إلى ملف app/build.gradle
:
Groovy
android { ... compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }
Kotlin
android { ... compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } }
فئة تطبيق Hilt
يجب أن تحتوي جميع التطبيقات التي تستخدم Hilt على
Application
التي تمت إضافة تعليقات توضيحية إليها
@HiltAndroidApp
تؤدي @HiltAndroidApp
إلى إنشاء رموز Hilt، بما في ذلك الفئة الأساسية
تطبيقك الذي يعمل كحاوية تبعية على مستوى التطبيق.
Kotlin
@HiltAndroidApp class ExampleApplication : Application() { ... }
Java
@HiltAndroidApp public class ExampleApplication extends Application { ... }
يتم ربط المكوِّن الذي تم إنشاؤه بخاصية Hilt بعنصر Application
.
دورة الحياة ويوفر التبعيات إليها. بالإضافة إلى ذلك، فهو المسؤول الرئيسي
من مكونات التطبيق، مما يعني أن المكونات الأخرى يمكنها الوصول إلى
والتبعيات التي توفرها.
إدخال الموارد التابعة في صفوف Android
بعد إعداد Hilt في صف Application
وعلى مستوى التطبيق
مدى التوفّر، يمكن أن يوفر Hilt تبعيات لفئات Android أخرى
التي تتضمّن التعليق التوضيحي @AndroidEntryPoint
:
Kotlin
@AndroidEntryPoint class ExampleActivity : AppCompatActivity() { ... }
Java
@AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { ... }
يتوافق Hilt حاليًا مع فئات Android التالية:
Application
(باستخدام@HiltAndroidApp
)ViewModel
(باستخدام@HiltViewModel
)Activity
Fragment
View
Service
BroadcastReceiver
إذا أضفت تعليقات توضيحية إلى صف في Android باستخدام "@AndroidEntryPoint
"، عليك أيضًا.
إضافة تعليقات توضيحية إلى فئات Android التي تعتمد عليها. على سبيل المثال، إذا قمت بإضافة تعليق توضيحي
فيجب عليك أيضًا إضافة تعليق توضيحي لأي أنشطة تستخدم فيها
.
ينشئ تطبيق "@AndroidEntryPoint
" مكوّن Hilt فردي لكل نظام Android.
الفصل في مشروعك. يمكن أن تتلقى هذه المكونات تبعيات من
الفئات الرئيسية المعنية كما هو موضح في المكوّن
التسلسل الهرمي:
للحصول على عناصر الاعتمادية من مكوِّن، استخدِم التعليق التوضيحي @Inject
لتنفيذ
إدخال الحقل:
Kotlin
@AndroidEntryPoint class ExampleActivity : AppCompatActivity() { @Inject lateinit var analytics: AnalyticsAdapter ... }
Java
@AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { @Inject AnalyticsAdapter analytics; ... }
يمكن أن تشتمل الفئات التي يتم حقنها عن طريق Hilt على فئات أساسية أخرى تستخدم الحقن أيضًا.
ولا تحتاج هذه الصفوف إلى التعليق التوضيحي @AndroidEntryPoint
إذا كانت
تجريدي.
لمعرفة المزيد من المعلومات حول دورة الحياة التي يتم فيها إدخال فئة Android، راجع أعمار المكوّنات.
تعريف عمليات ربط Hilt
ولإجراء حقن الحقل، يحتاج Hilt إلى معرفة طريقة توفير مثيلات والتبعيات الضرورية من المكون المقابل. يحتوي الربط على المعلومات اللازمة لتوفير مثيلات من نوع ما كتبعية.
إحدى الطرق لتقديم معلومات ملزمة إلى Hilt هي إدخال الدالة الإنشائية. استخدام
التعليق التوضيحي @Inject
على الدالة الإنشائية لفئة معيّنة لإعلام هيلت بكيفية
اذكر أمثلة من تلك الفئة:
Kotlin
class AnalyticsAdapter @Inject constructor( private val service: AnalyticsService ) { ... }
Java
public class AnalyticsAdapter { private final AnalyticsService service; @Inject AnalyticsAdapter(AnalyticsService service) { this.service = service; } ... }
معاملات الدالة الإنشائية التي تم التعليق عليها لفئة ما هي تبعيات
لتلك الفئة. في المثال، تتضمّن AnalyticsAdapter
السمة AnalyticsService
كسمة
والتبعية. ومن ثمّ، يتعين على Hilt أيضًا معرفة كيفية تقديم مثيلات
AnalyticsService
وحدات الجناح
أحيانًا لا يمكن إدخال دالة إنشائية. يمكن أن يحدث هذا لعدة الأسباب. على سبيل المثال، لا يمكنك إدخال دالة إنشائية لواجهة. يمكنك أيضًا لا يمكن لأداة الإنشاء إدخال نوع لا تملكه، مثل فئة من ومكتبة خارجية. في هذه الحالات، يمكنك تزويد Hilt بمعلومات ملزمة. باستخدام وحدات النتائج
وحدة Hilt هي فئة تمت إضافة تعليقات توضيحية إليها باستخدام @Module
. مثل Dagger
واحدة، فإنها
تُعلم Hilt كيفية توفير مثيلات من أنواع معيّنة. وعلى عكس وحدات Dagger،
يجب إضافة تعليقات توضيحية إلى وحدات Hilt باستخدام @InstallIn
لإعلام Hilt بنظام Android.
الفئة التي سيتم استخدام أو تثبيت كل وحدة فيها.
تكون التبعيات التي تقدّمها في وحدات Hilt متاحة في جميع المهام التي تم إنشاؤها. المرتبطة بفئة Android حيث يتم تثبيت وحدة Hilt
إدخال حالات الواجهة باستخدام @Binds
يمكنك الاطّلاع على المثال AnalyticsService
. إذا كانت AnalyticsService
واجهة،
فلن يمكنك تضمين الدالة الإنشائية. بدلاً من ذلك، عليك تزويد Hilt بالربط
عن طريق إنشاء دالة مجردة مع تعليقات توضيحية باستخدام @Binds
داخلها
وحدة Hilt
يحدّد التعليق التوضيحي @Binds
أنّ Hilt يحدد طريقة التنفيذ التي يجب استخدامها عندما يكون هناك حاجة إلى ذلك.
تقدم مثيلاً للواجهة.
توفّر الدالة التي تحتوي على تعليقات توضيحية المعلومات التالية لجهة Hilt:
- تخبر الدالة return type Hilt بالواجهة التي توفرها الدالة. منه.
- تُستخدَم مَعلمة الدالة لتخبر Hilt بأي عملية تنفيذ يجب توفيرها.
Kotlin
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 }
Java
public interface AnalyticsService { void analyticsMethods(); } // Constructor-injected, because Hilt needs to know how to // provide instances of AnalyticsServiceImpl, too. public class AnalyticsServiceImpl implements AnalyticsService { ... @Inject AnalyticsServiceImpl(...) { ... } } @Module @InstallIn(ActivityComponent.class) public abstract class AnalyticsModule { @Binds public abstract AnalyticsService bindAnalyticsService( AnalyticsServiceImpl analyticsServiceImpl ); }
تتم إضافة تعليقات توضيحية إلى وحدة Hilt AnalyticsModule
.
@InstallIn(ActivityComponent.class)
لأنك تريد أن يُدخل Hilt تلك البيانات
التبعية إلى ExampleActivity
. يعني هذا التعليق التوضيحي أن جميع
تتوفر الموارد التابعة في AnalyticsModule
في جميع أنشطة التطبيق.
إدخال مثيلات باستخدام @Provides
لا تكون الواجهات هي الحالة الوحيدة التي لا يمكنك فيها إدخال نوع من الدالة الإنشائية.
ومن غير الممكن أيضًا إدخال الدالة الإنشائية إذا لم تكن تملك الفئة لأنها
من مكتبة خارجية (فصول مثل
المراجعة النهائية،
OkHttpClient
،
أو قواعد بيانات الغرف)، أو إذا كان يجب
سيتم إنشاؤها باستخدام المنشئ
التصميم.
بالنظر إلى المثال السابق. إذا لم تكن تملك AnalyticsService
بشكل مباشر
يمكنك إخبار Hilt بكيفية تقديم مثيلات من هذا النوع عن طريق إنشاء
داخل وحدة Hilt وإضافة تعليقات توضيحية إلى هذه الدالة باستخدام @Provides
.
توفّر الدالة المُشار إليها المعلومات التالية إلى Hilt:
- تخبر الدالة return type Hilt بنوع الدالة الذي توفره المثيلات منه.
- تخبر معاملات الدالة Hilt بتبعيات النوع المقابل.
- يخبر نص الدالة Hilt بكيفية تقديم مثيل الكتابة. ينفذ Hilt نص الدالة في كل مرة يحتاج فيها إلى توفير مثيل من هذا النوع.
Kotlin
@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) } }
Java
@Module @InstallIn(ActivityComponent.class) public class AnalyticsModule { @Provides public static AnalyticsService provideAnalyticsService( // Potential dependencies of this type ) { return new Retrofit.Builder() .baseUrl("https://example.com") .build() .create(AnalyticsService.class); } }
توفير عمليات ربط متعدّدة للنوع نفسه
في الحالات التي تحتاج فيها إلى تقديم Hilt لعمليات تنفيذ مختلفة كتبعيات، فيجب عليك تزويد Hilt بروابط متعددة. يمكنك تحديد عمليات ربط متعددة لنفس النوع باستخدام المؤهلات.
المؤهِّل هو تعليق توضيحي تستخدمه لتحديد ارتباط معين لـ عندما يكون لهذا النوع ارتباطات متعددة محددة.
ضع في الاعتبار المثال. إذا أردت اعتراض المكالمات الواردة إلى AnalyticsService
، عليك
يمكن استخدام كائن OkHttpClient
مع
أداة الاعتراض بالنسبة
والخدمات الأخرى، فقد تحتاج إلى اعتراض المكالمات بطريقة مختلفة. في ذلك،
عليك إخبار Hilt بكيفية تقديم عمليتَي تنفيذ مختلفتَين
OkHttpClient
عليك أولاً تحديد المؤهِّلات التي ستستخدمها لإضافة تعليقات توضيحية إلى السمة @Binds
أو.
طريقتان (@Provides
):
Kotlin
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class AuthInterceptorOkHttpClient @Qualifier @Retention(AnnotationRetention.BINARY) annotation class OtherInterceptorOkHttpClient
Java
@Qualifier @Retention(RetentionPolicy.RUNTIME) private @interface AuthInterceptorOkHttpClient {} @Qualifier @Retention(RetentionPolicy.RUNTIME) private @interface OtherInterceptorOkHttpClient {}
بعد ذلك، تحتاج هيلت إلى معرفة كيفية تقديم مثيل من النوع الذي يتوافق
مع كل مؤهل. وفي هذه الحالة، يمكنك استخدام وحدة Hilt مع @Provides
.
كلتا الطريقتين لهما نفس نوع الإرجاع، لكن المؤهلات تصنفهما على أنهما
الأربطة المختلفة:
Kotlin
@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() } }
Java
@Module @InstallIn(ActivityComponent.class) public class NetworkModule { @AuthInterceptorOkHttpClient @Provides public static OkHttpClient provideAuthInterceptorOkHttpClient( AuthInterceptor authInterceptor ) { return new OkHttpClient.Builder() .addInterceptor(authInterceptor) .build(); } @OtherInterceptorOkHttpClient @Provides public static OkHttpClient provideOtherInterceptorOkHttpClient( OtherInterceptor otherInterceptor ) { return new OkHttpClient.Builder() .addInterceptor(otherInterceptor) .build(); } }
يمكنك إدخال النوع المحدد الذي تريده عن طريق التعليق التوضيحي على الحقل أو مع المؤهِّل المقابل:
Kotlin
// 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: AppCompatActivity() { @AuthInterceptorOkHttpClient @Inject lateinit var okHttpClient: OkHttpClient }
Java
// As a dependency of another class. @Module @InstallIn(ActivityComponent.class) public class AnalyticsModule { @Provides public static AnalyticsService provideAnalyticsService( @AuthInterceptorOkHttpClient OkHttpClient okHttpClient ) { return new Retrofit.Builder() .baseUrl("https://example.com") .client(okHttpClient) .build() .create(AnalyticsService.class); } } // As a dependency of a constructor-injected class. public class ExampleServiceImpl ... { private final OkHttpClient okHttpClient; @Inject ExampleServiceImpl(@AuthInterceptorOkHttpClient OkHttpClient okHttpClient) { this.okHttpClient = okHttpClient; } } // At field injection. @AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { @AuthInterceptorOkHttpClient @Inject OkHttpClient okHttpClient; ... }
كأفضل ممارسة، إذا أضفت مؤهِّل إلى نوع ما، فستضيف مؤهِّلات إلى جميع الطرق الممكنة لتوفير تلك التبعية. ترك القاعدة أو الشائع التنفيذ بدون مؤهِّل يكون عرضة للخطأ وقد يؤدي إلى Hilt لإدخال تبعية خاطئة.
المؤهلات المحددة مسبقًا في Hilt
يوفّر Hilt بعض المؤهلات المحدّدة مسبقًا. على سبيل المثال، قد تحتاج إلى
Context
من التطبيق أو النشاط، يوفر Hilt
الفريقان: @ApplicationContext
و@ActivityContext
لنفترض أنّ الفئة AnalyticsAdapter
من المثال تحتاج إلى سياق
النشاط. توضح التعليمة البرمجية التالية كيفية توفير النشاط
سياق إلى AnalyticsAdapter
:
Kotlin
class AnalyticsAdapter @Inject constructor( @ActivityContext private val context: Context, private val service: AnalyticsService ) { ... }
Java
public class AnalyticsAdapter { private final Context context; private final AnalyticsService service; @Inject AnalyticsAdapter( @ActivityContext Context context, AnalyticsService service ) { this.context = context; this.service = service; } }
بالنسبة إلى عمليات الربط المحدّدة مسبقًا الأخرى المتوفّرة في Hilt، يُرجى الاطّلاع على القسم الإعداد التلقائي للمكوّن الإضافي. .
المكونات التي تم إنشاؤها لفئات Android
لكل فئة من فئات Android يمكنك فيها إدخال الحقل، هناك
مكوِّن Hilt المرتبط الذي يمكنك الرجوع إليه في تعليق @InstallIn
التوضيحي
يكون كل مكون من مكونات Hilt مسؤولًا عن ضخ ارتباطاته في
فئة Android المقابلة.
أظهرت الأمثلة السابقة استخدام ActivityComponent
في Hilt
الوحدات.
توفّر Hilt المكونات التالية:
مكوّن Hilt | حاقن |
---|---|
SingletonComponent |
Application |
ActivityRetainedComponent |
لا ينطبق |
ViewModelComponent |
ViewModel |
ActivityComponent |
Activity |
FragmentComponent |
Fragment |
ViewComponent |
View |
ViewWithFragmentComponent |
تمت إضافة تعليقات توضيحية من قِبل "View " باستخدام @WithFragmentBindings . |
ServiceComponent |
Service |
العمر الافتراضي للمكوّنات
ينشئ Hilt تلقائيًا نُسخًا من فئات المكوّنات التي تم إنشاؤها ويدمرها. بعد دورة حياة فئات Android المقابلة.
المكوّن الذي تم إنشاؤه | وقت الإنشاء: | تاريخ التدمير |
---|---|---|
SingletonComponent |
Application#onCreate() |
تمت إزالة Application . |
ActivityRetainedComponent |
Activity#onCreate() |
Activity#onDestroy() |
ViewModelComponent |
تم إنشاء ViewModel . |
تمت إزالة ViewModel . |
ActivityComponent |
Activity#onCreate() |
Activity#onDestroy() |
FragmentComponent |
Fragment#onAttach() |
Fragment#onDestroy() |
ViewComponent |
View#super() |
تمت إزالة View . |
ViewWithFragmentComponent |
View#super() |
تمت إزالة View . |
ServiceComponent |
Service#onCreate() |
Service#onDestroy() |
نطاقات المكوّنات
تكون جميع عمليات الربط في Hilt غير محدَّدة تلقائيًا. هذا يعني أنه في كل مرة يطلب التطبيق الربط، ينشئ Hilt مثيلاً جديدًا من النوع المطلوب.
في هذا المثال، في كل مرة يوفر فيها Hilt AnalyticsAdapter
كاعتمادية،
من خلال نوع آخر أو من خلال حقن الحقل (كما في ExampleActivity
)، يوفر Hilt
مثيل جديد لـ AnalyticsAdapter
.
ومع ذلك، تسمح Hilt أيضًا بتحديد نطاق الربط لمكون معيَّن. أعلى درجة يؤدي فقط إلى إنشاء ربط واسع النطاق مرة واحدة فقط لكل مثيل من المكون الذي يتم تحديد نطاقه، وأن جميع الطلبات لهذا الربط تشترك في المثيل نفسه.
يسرد الجدول أدناه التعليقات التوضيحية للنطاق لكل مكون تم إنشاؤه:
حصة Android | المكوّن الذي تم إنشاؤه | المجال |
---|---|---|
Application |
SingletonComponent |
@Singleton |
Activity |
ActivityRetainedComponent |
@ActivityRetainedScoped |
ViewModel |
ViewModelComponent |
@ViewModelScoped |
Activity |
ActivityComponent |
@ActivityScoped |
Fragment |
FragmentComponent |
@FragmentScoped |
View |
ViewComponent |
@ViewScoped |
تمت إضافة تعليقات توضيحية من قِبل "View " باستخدام @WithFragmentBindings . |
ViewWithFragmentComponent |
@ViewScoped |
Service |
ServiceComponent |
@ServiceScoped |
في المثال، إذا طبّقت النطاق AnalyticsAdapter
على ActivityComponent
باستخدام @ActivityScoped
، يوفّر Hilt الحالة نفسها من AnalyticsAdapter
طوال عمر النشاط المقابل:
Kotlin
@ActivityScoped class AnalyticsAdapter @Inject constructor( private val service: AnalyticsService ) { ... }
Java
@ActivityScoped public class AnalyticsAdapter { private final AnalyticsService service; @Inject AnalyticsAdapter(AnalyticsService service) { this.service = service; } ... }
لنفترض أن AnalyticsService
هي حالة داخلية تتطلب الأمر نفسه
يُستخدم في كل مرة - ليس فقط في ExampleActivity
، ولكن في أي مكان في
التطبيق. في هذه الحالة، من المناسب تحديد نطاق AnalyticsService
إلى
SingletonComponent
والنتيجة هي أنه كلما احتاج المكون إلى
تقديم مثيل AnalyticsService
، فإنه يوفر المثيل نفسه كل
الوقت.
يوضح المثال التالي كيفية تعيين نطاق ربط لمكون في
وحدة Hilt يجب أن يتطابق نطاق الربط مع نطاق المكوِّن حيث يكون
، لذا يجب في هذا المثال تثبيت AnalyticsService
في
SingletonComponent
بدلاً من ActivityComponent
:
Kotlin
// 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) } }
Java
// If AnalyticsService is an interface. @Module @InstallIn(SingletonComponent.class) public abstract class AnalyticsModule { @Singleton @Binds public abstract AnalyticsService bindAnalyticsService( AnalyticsServiceImpl analyticsServiceImpl ); } // If you don't own AnalyticsService. @Module @InstallIn(SingletonComponent.class) public class AnalyticsModule { @Singleton @Provides public static AnalyticsService provideAnalyticsService() { return new Retrofit.Builder() .baseUrl("https://example.com") .build() .create(AnalyticsService.class); } }
لمزيد من المعلومات حول نطاقات مكوّنات Hilt، يُرجى الاطّلاع على المقالة تحديد النطاق في Android Hilt.
التدرّج الهرمي للمكوّنات
يسمح تثبيت وحدة في مكوَّن بالوصول إلى روابطها كوحدة تبعية الأربط الأخرى في هذا المكون أو في أي مكون فرعي أدناه في التسلسل الهرمي للمكونات:
عمليات الربط التلقائية للمكوّنات
يأتي كل مكوّن Hilt مزودًا بمجموعة من عمليات الربط التلقائية التي يمكن لتطبيق Hilt إدخالها والتبعيات في الروابط المخصصة الخاصة بك. لاحظ أن هذه الارتباطات تتجاوب على النشاط العام وأنواع الأجزاء وليس بأي فئة فرعية محددة. والسبب في ذلك هو أنّ Hilt تستخدم تعريفًا واحدًا لمكون النشاط لإدخال جميع والأنشطة السابقة. لكل نشاط مثيل مختلف من هذا المكون.
مكوِّن Android | عمليات الربط التلقائية |
---|---|
SingletonComponent |
Application |
ActivityRetainedComponent |
Application |
ViewModelComponent |
SavedStateHandle |
ActivityComponent |
Application ، Activity |
FragmentComponent |
Application وActivity وFragment |
ViewComponent |
Application وActivity وView |
ViewWithFragmentComponent |
Application ، Activity ، Fragment ، View |
ServiceComponent |
Application ، Service |
يتوفّر ربط سياق التطبيق أيضًا باستخدام @ApplicationContext
.
مثلاً:
Kotlin
class AnalyticsServiceImpl @Inject constructor( @ApplicationContext context: Context ) : AnalyticsService { ... } // The Application binding is available without qualifiers. class AnalyticsServiceImpl @Inject constructor( application: Application ) : AnalyticsService { ... }
Java
public class AnalyticsServiceImpl implements AnalyticsService { private final Context context; @Inject AnalyticsAdapter(@ApplicationContext Context context) { this.context = context; } } // The Application binding is available without qualifiers. public class AnalyticsServiceImpl implements AnalyticsService { private final Application application; @Inject AnalyticsAdapter(Application application) { this.application = application; } }
تتوفّر ميزة ربط سياق النشاط أيضًا باستخدام ميزة "@ActivityContext
". بالنسبة
مثال:
Kotlin
class AnalyticsAdapter @Inject constructor( @ActivityContext context: Context ) { ... } // The Activity binding is available without qualifiers. class AnalyticsAdapter @Inject constructor( activity: FragmentActivity ) { ... }
Java
public class AnalyticsAdapter { private final Context context; @Inject AnalyticsAdapter(@ActivityContext Context context) { this.context = context; } } // The Activity binding is available without qualifiers. public class AnalyticsAdapter { private final FragmentActivity activity; @Inject AnalyticsAdapter(FragmentActivity activity) { this.activity = activity; } }
إدخال تبعيات في فئات لا يدعمها Hilt
تأتي Hilt متوافقة مع فئات Android الأكثر شيوعًا. ومع ذلك، قد بحاجة إلى إجراء حقن الحقل في فئات لا يدعمها Hilt.
وفي هذه الحالات، يمكنك إنشاء نقطة دخول باستخدام @EntryPoint
.
التعليق التوضيحي. نقطة الدخول هي الحد الفاصل بين الرمز الذي يديره Hilt
والرموز غير البرمجية غير ذلك. إنها النقطة التي يتم فيها إدخال الرمز لأول مرة في الرسم البياني
الأخرى التي يديرها Hilt. تسمح نقاط الإدخال للدالة Hilt باستخدام الرمز الذي ينشئه Hilt
عدم القدرة على تقديم التبعيات داخل الرسم البياني للتبعية.
على سبيل المثال، لا تتوافق Hilt مباشرةً مع المحتوى
. إذا أردت محتوًى
استخدام Hilt للحصول على بعض التبعيات، يجب تحديد واجهة
التي تتم إضافة تعليقات توضيحية إليها باستخدام @EntryPoint
لكل نوع ربط تريده
المؤهِّلات. بعد ذلك، أضِف @InstallIn
لتحديد المكوِّن الذي تريد
تثبيت نقطة الدخول على النحو التالي:
Kotlin
class ExampleContentProvider : ContentProvider() { @EntryPoint @InstallIn(SingletonComponent::class) interface ExampleContentProviderEntryPoint { fun analyticsService(): AnalyticsService } ... }
Java
public class ExampleContentProvider extends ContentProvider { @EntryPoint @InstallIn(SingletonComponent.class) interface ExampleContentProviderEntryPoint { public AnalyticsService analyticsService(); } ... }
للوصول إلى نقطة دخول، استخدم الطريقة الثابتة المناسبة من
EntryPointAccessors
يجب أن تكون المعلمة إما مثيل المكون أو
الكائن @AndroidEntryPoint
الذي يعمل كصاحب العنصر. يُرجى التأكد من أنّ:
من أن المكون الذي تمرره كمعلمة والعامل الثابت EntryPointAccessors
تتطابق كلتاهما مع فئة Android في التعليق التوضيحي @InstallIn
على
واجهة "@EntryPoint
":
Kotlin
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() ... } }
Java
public class ExampleContentProvider extends ContentProvider { @Override public Cursor query(...) { Context appContext = getContext().getApplicationContext(); ExampleContentProviderEntryPoint hiltEntryPoint = EntryPointAccessors.fromApplication(appContext, ExampleContentProviderEntryPoint.class); AnalyticsService analyticsService = hiltEntryPoint.analyticsService(); } }
في هذا المثال، يجب استخدام ApplicationContext
لاسترداد الإدخال.
لأنّه تم تثبيت نقطة الدخول في SingletonComponent
. إذا كانت
التي تريد استردادها كانت في ActivityComponent
، سوف تحتاج إلى
يمكنك استخدام ActivityContext
بدلاً من ذلك
أداة Hilt وخنجر
تم بناء Hilt أعلى أداة Dagger. وهي مكتبة حقن التبعية، مما يوفر طريقة معيارية لدمج Dagger في تطبيق Android.
في ما يتعلق بأداة Dagger، تتمثل أهداف Hilt في ما يلي:
- لتبسيط البنية الأساسية المتعلقة بأداة Dagger في تطبيقات Android.
- لإنشاء مجموعة قياسية من المكونات والنطاقات لتسهيل الإعداد، وسهولة القراءة، ومشاركة الرموز بين التطبيقات
- لتوفير طريقة سهلة لتوفير روابط مختلفة لأنواع مختلفة من التصميمات، مثل الاختبار أو تصحيح الأخطاء أو الإصدار.
لأنّ نظام التشغيل Android ينشئ مثيلاً للعديد من إطار العمل الخاص به فإن استخدام Dagger في أحد تطبيقات Android يتطلب كتابة مجموعة كبيرة مقدار النص النموذجي. يقلل Hilt من رمز النص النموذجي المضمّن في باستخدام Dagger في أحد تطبيقات Android. تقوم Hilt تلقائيًا بإنشاء ما يلي:
- مكونات دمج فئات أطر عمل Android مع Dagger التي سيحتاج إلى إنشائها يدويًا بخلاف ذلك.
- تعليقات توضيحية للنطاق لاستخدامها مع المكوّنات التي ينشئها Hilt تلقائيًا.
- عمليات الربط المحدَّدة مسبقًا لتمثيل فئات Android، مثل
Application
أوActivity
- المؤهلات المحدّدة مسبقًا لتمثيل
@ApplicationContext
@ActivityContext
يمكن أن يتواجد رمزا Dagger وHlt في نفس قاعدة الرموز. ومع ذلك، في معظم الحالات هو أفضل استخدام Hilt لإدارة كل استخدامك لأداة Dagger على Android. لنقل البيانات يستخدم Dagger إلى Hilt، راجع قسم نقل البيانات ودليل نقل البيانات تطبيق Dagger على Hilt درس تطبيقي حول الترميز.
مصادر إضافية
لمعرفة المزيد من المعلومات عن Hilt، يمكنك الاطّلاع على المراجع الإضافية التالية.
نماذج
الدروس التطبيقية حول الترميز
المدوّنات
- تطبيق Dependency Injection على Android مع Hilt
- تحديد النطاق في Android Hilt
- إضافة عناصر إلى Hilt التدرّج الهرمي
- نقل تطبيق مؤتمر Google I/O إلى Hilt