Hilt هي مكتبة حقن التبعية لنظام Android من شأنها الحد من النص النموذجي. من تنفيذ حقن التبعية اليدوية في مشروعك. تنفيذ التبعية اليدوية حقن البيانات تتطلب منك إنشاء كل فئة وتبعياتها يدويًا، واستخدام الحاويات لإعادة استخدام وإدارة التبعيات.
توفّر Hilt طريقة قياسية لاستخدام "التبعية التعريفية" في تطبيقك من خلال توفير حاويات لكل فئة Android في مشروعك وإدارة دورات حياتها تلقائيًا. تم بناء Hilt فوق مكتبة DI الشهيرة. يمكنك استخدام Dagger للاستفادة من صحة وقت التجميع وأداء وقت التشغيل وقابلية التوسّع واستوديو Android الدعم التي توفرها أداة Dagger. لمزيد من المعلومات، يُرجى الاطّلاع على مقبض السيف والخنجر.
يشرح هذا الدليل المفاهيم الأساسية لتطبيق Hilt والحاويات التي يتم إنشاؤها. ويتضمن أيضًا عرضًا توضيحيًا لكيفية بدء تشغيل تطبيق حالي لاستخدام Hilt.
إضافة التبعيات
أولاً، أضِف المكوّن الإضافي hilt-android-gradle-plugin
إلى ملف ملف build.gradle
الجذر لمشروعك:
plugins { ... id 'com.google.dagger.hilt.android' version '2.51.1' apply false }
plugins { ... id("com.google.dagger.hilt.android") version "2.51.1" apply false }
ثم قم بتطبيق المكون الإضافي Gradle وإضافة هذه التبعيات في
ملف app/build.gradle
:
... plugins { id 'kotlin-kapt' id 'com.google.dagger.hilt.android' } android { ... } dependencies { implementation "com.google.dagger:hilt-android:2.51.1" kapt "com.google.dagger:hilt-compiler:2.51.1" } // Allow references to generated code kapt { correctErrorTypes true }
plugins { id("kotlin-kapt") id("com.google.dagger.hilt.android") } android { ... } dependencies { implementation("com.google.dagger:hilt-android:2.51.1") kapt("com.google.dagger:hilt-android-compiler:2.51.1") } // Allow references to generated code kapt { correctErrorTypes = true }
يستخدم Hilt ميزات Java 8. لتفعيل Java 8 في
مشروعك، أضِف ما يلي إلى ملف app/build.gradle
:
android { ... compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }
android { ... compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } }
فئة تطبيق Hilt
يجب أن تحتوي جميع التطبيقات التي تستخدم Hilt على فئة
Application
تمّت إضافة تعليقات توضيحية لها باستخدام
@HiltAndroidApp
.
تؤدي @HiltAndroidApp
إلى إنشاء رموز Hilt، بما في ذلك الفئة الأساسية
تطبيقك الذي يعمل كحاوية تبعية على مستوى التطبيق.
@HiltAndroidApp class ExampleApplication : Application() { ... }
@HiltAndroidApp public class ExampleApplication extends Application { ... }
يتم ربط المكوِّن الذي تم إنشاؤه بخاصية Hilt بعنصر Application
.
دورة الحياة ويوفر التبعيات لها. بالإضافة إلى ذلك، هو المكوّن
الأساسي للتطبيق، ما يعني أنّ المكونات الأخرى يمكنها الوصول إلى
التبعيات التي يوفّرها.
إدخال الموارد التابعة في صفوف Android
بعد إعداد Hilt في فئة Application
وتوفير ملف برمجي
على مستوى التطبيق، يمكن أن يوفّر Hilt تبعيات لفئات Android
أخرى تتضمّن التعليق التوضيحي @AndroidEntryPoint
:
@AndroidEntryPoint class ExampleActivity : AppCompatActivity() { ... }
@AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { ... }
تتيح أداة Hilt حاليًا فئات Android التالية:
Application
(باستخدام@HiltAndroidApp
)ViewModel
(باستخدام@HiltViewModel
)Activity
Fragment
View
Service
BroadcastReceiver
إذا أضفت تعليقًا توضيحيًا إلى فئة Android باستخدام @AndroidEntryPoint
، عليك أيضًا
إضافة تعليقات توضيحية إلى فئات Android التي تعتمد عليها. على سبيل المثال، إذا قمت بإضافة تعليق توضيحي
فيجب عليك أيضًا إضافة تعليق توضيحي لأي أنشطة تستخدم فيها
.
ينشئ تطبيق "@AndroidEntryPoint
" مكوّن Hilt فردي لكل نظام Android.
الفصل في مشروعك. يمكن أن تتلقّى هذه المكوّنات تبعيات من
فئاتها الرئيسية المعنيّة كما هو موضّح في تدرّج
المكوّنات.
للحصول على عناصر الاعتمادية من مكوِّن، استخدِم التعليق التوضيحي @Inject
لتنفيذ
إدخال الحقل:
@AndroidEntryPoint class ExampleActivity : AppCompatActivity() { @Inject lateinit var analytics: AnalyticsAdapter ... }
@AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { @Inject AnalyticsAdapter analytics; ... }
يمكن أن تشتمل الفئات التي يتم حقنها عن طريق Hilt على فئات أساسية أخرى تستخدم الحقن أيضًا.
ولا تحتاج هذه الصفوف إلى التعليق التوضيحي @AndroidEntryPoint
إذا كانت
تجريدي.
لمعرفة المزيد من المعلومات عن دالة الاستدعاء التي تُستخدَم في دورة حياة فئة Android، اطّلِع على مدّة حياة المكوّنات.
تعريف عمليات ربط Hilt
لتنفيذ حقن الحقول، يجب أن تعرف Hilt كيفية توفير نُسخ من التبعيات الضرورية من المكوّن المقابل. يحتوي الربط على المعلومات اللازمة لتوفير مثيلات من نوع ما كتبعية.
من الطرق التي تتيح تقديم معلومات الربط إلى Hilt هي حقن مُنشئ العنصر. استخدِم التعليق التوضيحي @Inject
على الدالة الإنشائية لفئة معيّنة لإعلام Hilt بكيفية
توفير نُسخ من تلك الفئة:
class AnalyticsAdapter @Inject constructor( private val service: AnalyticsService ) { ... }
public class AnalyticsAdapter { private final AnalyticsService service; @Inject AnalyticsAdapter(AnalyticsService service) { this.service = service; } ... }
معاملات الدالة الإنشائية التي تم التعليق عليها لفئة ما هي تبعيات
لتلك الفئة. في المثال، تتضمّن AnalyticsAdapter
السمة AnalyticsService
كسمة
والتبعية. ومن ثمّ، يتعين على Hilt أيضًا معرفة كيفية تقديم مثيلات
AnalyticsService
وحدات Hilt
أحيانًا لا يمكن إدخال دالة إنشائية. يمكن أن يحدث هذا لعدة الأسباب. على سبيل المثال، لا يمكنك إدخال دالة إنشاء واجهة. يمكنك أيضًا لا يمكن لأداة الإنشاء إدخال نوع لا تملكه، مثل فئة من ومكتبة خارجية. في هذه الحالات، يمكنك تزويد Hilt بمعلومات الربط باستخدام وحدات 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 بتنفيذ أيّ منها.
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 }
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:
- يُخبر نوع عرض الدالة أداة 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) } }
@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
:
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class AuthInterceptorOkHttpClient @Qualifier @Retention(AnnotationRetention.BINARY) annotation class OtherInterceptorOkHttpClient
@Qualifier @Retention(RetentionPolicy.RUNTIME) private @interface AuthInterceptorOkHttpClient {} @Qualifier @Retention(RetentionPolicy.RUNTIME) private @interface 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() } }
@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(); } }
يمكنك إدخال النوع المحدد الذي تريده عن طريق التعليق التوضيحي على الحقل أو مع المؤهِّل المقابل:
// 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 }
// 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
سياق النشاط:
class AnalyticsAdapter @Inject constructor( @ActivityContext private val context: Context, private val service: AnalyticsService ) { ... }
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
طوال مدة النشاط المقابل:
@ActivityScoped class AnalyticsAdapter @Inject constructor( private val service: AnalyticsService ) { ... }
@ActivityScoped public class AnalyticsAdapter { private final AnalyticsService service; @Inject AnalyticsAdapter(AnalyticsService service) { this.service = service; } ... }
لنفترض أن 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) } }
// 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
.
مثلاً:
class AnalyticsServiceImpl @Inject constructor( @ApplicationContext context: Context ) : AnalyticsService { ... } // The Application binding is available without qualifiers. class AnalyticsServiceImpl @Inject constructor( application: Application ) : AnalyticsService { ... }
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
. على سبيل المثال:
class AnalyticsAdapter @Inject constructor( @ActivityContext context: Context ) { ... } // The Activity binding is available without qualifiers. class AnalyticsAdapter @Inject constructor( activity: FragmentActivity ) { ... }
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 للحصول على بعض التبعيات، عليك تحديد واجهة
مُشارَك فيها تعليقًا توضيحيًا باستخدام @EntryPoint
لكل نوع ربط تريده،
وتضمين المحدِّفات. بعد ذلك، أضِف @InstallIn
لتحديد المكوِّن الذي تريد
تثبيت نقطة الدخول على النحو التالي:
class ExampleContentProvider : ContentProvider() { @EntryPoint @InstallIn(SingletonComponent::class) interface ExampleContentProviderEntryPoint { fun analyticsService(): AnalyticsService } ... }
public class ExampleContentProvider extends ContentProvider { @EntryPoint @InstallIn(SingletonComponent.class) interface ExampleContentProviderEntryPoint { public 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() ... } }
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 وHilt قاعدة الرموز البرمجية نفسها. ومع ذلك، في معظم الحالات هو أفضل استخدام Hilt لإدارة كل استخدامك لأداة Dagger على Android. لنقل مشروع يستخدم Dagger إلى Hilt، اطّلِع على دليل نقل البيانات ونقل بيانات تطبيقك الذي يستخدم Dagger إلى Hilt في codelab.
مصادر إضافية
لمزيد من المعلومات عن Hilt، اطّلِع على المراجع الإضافية التالية.
نماذج
تعرَّف على كيفية تنفيذ عمليات الضبط المُدارة التي يمكن أن تغيّرها تطبيقات أخرى على الجهاز نفسه. توفِّر ميزات المؤسسة من Android للمؤسسات بيئة آمنة ومرنة نظام Android للجوّال الأساسي الموحد — الذي يجمع بين الأجهزة والتطبيقات والإدارة. تطبيقات Android متوافقة مع ميزات المؤسسة من Android تلقائيًا. ومع ذلك، هناك ميزات إضافية يمكنك استخدامها لإنشاء تعرَّف على كيفية التأكُّد من عمل تطبيقاتك بسلاسة في بيئة الشركة من خلال اتّباع بعض أفضل الممارسات.إعداد عمليات الضبط المُدارة
دليل مطوّري البرامج
الملفات الشخصية للعمل
الدروس التطبيقية حول الترميز
المدوّنات
- تطبيق Dependency Injection على Android مع Hilt
- تحديد النطاق في Android و Hilt
- إضافة عناصر إلى Hilt التدرّج الهرمي
- نقل بيانات تطبيق Google I/O إلى IDE Hilt