Hilt היא ספריית הזרקת תלות ל-Android שמפחיתה את שיעור החימום של החדרת תלות ידנית בפרויקט. ביצוע תלות ידנית החדרת נתונים דורשת מכם ליצור בכל רמה ויחסי התלות שלה באופן ידני, ולהשתמש בקונטיינרים כדי לעשות שימוש חוזר לנהל יחסי תלות.
Hilt מספק דרך סטנדרטית לשימוש ב-DI באפליקציה שלכם, קונטיינרים לכל מחלקה של Android בפרויקט וניהול מחזורי החיים שלהם באופן אוטומטי. Hilt מבוסס על ספריית DI הפופולרית Dagger כדי להפיק תועלת נכונות זמן הידור (compile), ביצועים בזמן ריצה, מדרגיות (scalability) ו-Android Studio תמיכה ש-Dagger. מידע נוסף זמין בקטע Hilt ו צלבון.
במדריך הזה מוסברים המושגים הבסיסיים של Hilt והקונטיינרים שנוצרו בה. הוא כוללת גם הדגמה של הפעלת אתחול אפליקציה קיימת כדי להשתמש ב-Hilt.
הוספת יחסי תלות
קודם כול, מוסיפים את הפלאגין hilt-android-gradle-plugin
לרמה הבסיסית (root) של הפרויקט
קובץ build.gradle
:
מגניב
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
:
מגניב
... 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
:
מגניב
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 חייבות להכיל
כיתה 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
לפעמים אי אפשר להזריק סוג מסוים באמצעות constructor. מצב כזה יכול לקרות בכמה סיבות נוספות. לדוגמה, אי אפשר להחדיר ממשק באמצעות constructor. בנוסף, לא יכול constructor להחדיר סוג שאינו בבעלותך, כמו מחלקה מ- היא ספרייה חיצונית. במקרים כאלה, אפשר לספק את Hilt עם מידע מחייב באמצעות מודולים של Hilt.
מודול Hilt הוא מחלקה שיש לה הערות עם @Module
. לסמן לייק לפגיעים
מודול,
מיידעים את Hilt איך לספק מופעים מסוגים מסוימים. בניגוד למודולים של Dagger,
צריך להוסיף הערות למודולים של Hilt באמצעות @InstallIn
כדי לומר ל-Hilt לאיזה Android
הכיתה שבה ייעשה שימוש או יותקן בכל מודול.
יחסי התלות שמספקים במודולים של Hilt זמינים בכל שמשויכים למחלקה של Android שבה מתקינים את מודול Hilt.
החדרת מופעי ממשק עם @Binds
עיינו בדוגמה AnalyticsService
. אם AnalyticsService
הוא ממשק,
אי אפשר להחדיר אותו באמצעות constructor. במקום זאת, צריך לספק את Hilt עם הקישור
מידע על ידי יצירת פונקציה מופשטת שמסומנת בהערה @Binds
בתוך
מודול Hilt.
ההערה @Binds
מנחה את Hilt באיזה הטמעה להשתמש כאשר היא צריכה
מספק מופע של ממשק.
הפונקציה עם ההערה מספקת ל-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)
כי ברצונך ש-Hhilt יכניס את הקובץ הזה
של תלות ב-ExampleActivity
. המשמעות של ההערה הזאת היא שכל
יחסי תלות ב-AnalyticsModule
זמינים בכל הפעילויות של האפליקציה.
החדרת מכונות עם @Provides
ממשקים הם לא המקרה היחיד שבו לא ניתן לבצע constructor להחדרת סוג.
בנוסף, לא ניתן לבצע החדרת בנייה אם אתם לא הבעלים של הכיתה, כי היא
מגיע מספרייה חיצונית (כיתות כמו
Retrofit,
OkHttpClient
,
או מסדי נתונים של חדר), או אם המופעים חייבים
ניתן ליצור באמצעות הבונה
דוגמת עיצוב.
נבחן את הדוגמה הקודמת. אם אתה לא הבעלים הישיר של AnalyticsService
אפשר להנחות את Hilt איך לספק מופעים מהסוג הזה על ידי יצירת
בתוך מודול Hilt ומוסיפים הערות לפונקציה באמצעות @Provides
.
הפונקציה עם ההערה מספקת את המידע הבא ל-Hilt:
- סוג ההחזרה של הפונקציה מציין ל-Hhilt איזה סוג הפונקציה מספקת מופעים מתוך.
- הפרמטרים של הפונקציה מציינים ל-Hhilt את יחסי התלות מהסוג המתאים.
- גוף הפונקציה מנחה את 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 צריך לדעת איך לספק מופע מהסוג שמתאים
עם כל פרמטר הגדרה. במקרה הזה, אפשר להשתמש במודול 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 מספק כמה קריטריונים מוגדרים מראש. לדוגמה, מכיוון שאולי צריך
הכיתה 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 מספק את הרכיבים הבאים:
רכיב רקמה | מזרק עבור |
---|---|
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 משתמש בהגדרה של רכיב פעילות יחיד כדי להחדיר את כל פעילויות. בכל פעילות יש מופע שונה של הרכיב הזה.
רכיב 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. אבל יכול להיות צריכים לבצע החדרת שדה במחלקות שלא נתמכות בהיטים.
במקרים כאלה, אפשר ליצור נקודת כניסה באמצעות @EntryPoint
הערה. נקודת כניסה היא הגבול בין קוד שמנוהל על ידי Hilt
ובקוד שאינו נכון. זו הנקודה שבה הקוד נכנס קודם בתרשים של
אובייקטים ש-Hhilt מנהלת. נקודות הכניסה מאפשרות ל-Hhilt להשתמש בקוד ש-Hhilt עושה
לא מאפשרות לספק יחסי תלות בתוך תרשים התלות.
לדוגמה, Hilt לא תומך ישירות בתוכן
ספקים. אם אתם רוצים לראות תוכן
להשתמש ב-Hhilt כדי לקבל יחסי תלות, צריך להגדיר ממשק
שנוסף לו הערות עם @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
ה-method תואם למחלקה של 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
.
הילט ופגיונות
ההילט בנוי על פגרת ספריית החדרת תלות, שמעניקה דרך סטנדרטית לשלב את Dagger לאפליקציה ל-Android.
ביחס ל-Dagger, היעדים של Hilt הם:
- כדי לפשט את התשתית שקשורה ל-Dagger לאפליקציות ל-Android.
- כדי ליצור קבוצה סטנדרטית של רכיבים והיקפים כדי להקל על ההגדרה, הקריאוּת, ושיתוף קוד בין אפליקציות.
- כדי לספק דרך קלה להקצות קישורים שונים לסוגי build שונים, כמו בדיקה, ניפוי באגים או פרסום.
כי מערכת ההפעלה Android יוצרת הרבה מה-framework שלה לשימוש ב-Dagger באפליקציה ל-Android, נדרש לכתוב כמות גדולה של סטנדרטי. Hilt מקטין את הקוד הסטנדרטי שמעורב באמצעות Dagger באפליקציה ל-Android. Hilt יוצר מספקת את הפרטים הבאים:
- רכיבים לשילוב שיעורי framework של Android עם Dagger שאחרת היה צריך ליצור ידנית.
- הערות היקף לשימוש עם הרכיבים ש-Hilt יוצר באופן אוטומטי.
- קישורים מוגדרים מראש לייצוג סיווגים של Android, כמו
Application
אוActivity
- מאפיינים מוגדרים מראש שמייצגים את
@ApplicationContext
@ActivityContext
קוד Dagger ו-Hilt יכולים להתקיים בו-זמנית באותו קוד בסיס. אבל ברוב המקרים, הכי טוב להשתמש ב-Hilt כדי לנהל את כל השימוש שלך ב-Dagger ב-Android. להעברה לפרויקט שמשתמש ב-Dagger ל-Hilt, ראו העברה הדרך ומעבר את אפליקציית Dagger to Hilt Codelab.
מקורות מידע נוספים
מידע נוסף על Hilt זמין במקורות המידע הנוספים הבאים.
דוגמיות
שיעורי Lab
בלוגים
- החדרת תלות ב-Android עם הכנסה
- קביעת היקף ב-Android ו הכנסה
- הוספת רכיבים ל-Hilt היררכיה
- להעביר את אפליקציית Google I/O אל הכנסה