Hilt היא ספריית הזרקת תלות ל-Android שמפחיתה את שיעור החימום של החדרת תלות ידנית בפרויקט. ביצוע תלות ידנית החדרת נתונים דורשת מכם ליצור בכל רמה ויחסי התלות שלה באופן ידני, ולהשתמש בקונטיינרים כדי לעשות שימוש חוזר לנהל יחסי תלות.
Hilt מספק דרך סטנדרטית לשימוש ב-DI באפליקציה שלכם, קונטיינרים לכל מחלקה של Android בפרויקט וניהול מחזורי החיים שלהם באופן אוטומטי. Hilt מבוסס על ספריית DI הפופולרית Dagger כדי להפיק תועלת נכונות זמן הידור (compile), ביצועים בזמן ריצה, מדרגיות (scalability) ו-Android Studio תמיכה ש-Dagger. מידע נוסף זמין במאמר Hilt and Dagger.
במדריך הזה מוסבר על המושגים הבסיסיים של Hilt ועל הקונטיינרים שנוצרים על ידו. בנוסף, תוכלו לראות הדגמה של איך להפעיל אפליקציה קיימת כדי להשתמש ב-Hilt.
הוספת יחסי תלות
קודם כול, מוסיפים את הפלאגין hilt-android-gradle-plugin
לרמה הבסיסית (root) של הפרויקט
קובץ 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
.
למידע נוסף על קריאה חוזרת (callback) של מחזור חיים שדרכה מוזרק מחלקה של Android, תוכלו לקרוא את המאמר משכי החיים של רכיבים.
הגדרת קישורים של Hilt
כדי לבצע החדרת שדה, Hilt צריך לדעת איך לספק מופעים של של יחסי התלות ההכרחיים מהרכיב המתאים. הקישור מכיל המידע הדרוש כדי לספק מופעים מסוג מסוים כתלות.
אחת הדרכים לספק מידע על קישור ל-Hilt היא הזרקה ל-constructor. כדי להורות ל-Hilt איך לספק מכונות של הכיתה הזו, משתמשים בהערה @Inject
ב-constructor של הכיתה:
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
לפעמים אי אפשר להחדיר סוג באמצעות ה-constructor. מצב כזה יכול לקרות בכמה סיבות נוספות. לדוגמה, אי אפשר להחדיר ממשק באמצעות constructor. בנוסף, לא יכול constructor להחדיר סוג שאינו בבעלותך, כמו מחלקה מ- לספרייה חיצונית. במקרים כאלה, אפשר לספק ל-Hilt את פרטי הקישור באמצעות מודולים של Hilt.
מודול Hilt הוא מחלקה עם הערה @Module
. בדומה למודול של Dagger, הוא מעדכן את Hilt איך לספק מופעים של סוגים מסוימים. בניגוד למודולים של Dagger,
צריך להוסיף הערות למודולים של Hilt באמצעות @InstallIn
כדי לומר ל-Hilt לאיזה Android
הכיתה שבה ייעשה שימוש או יותקן בכל מודול.
יחסי התלות שאתם מספקים במודולים של Hilt זמינים בכל הרכיבים שנוצרים ומשויכים לכיתה של Android שבה מתקינים את מודול Hilt.
הזרקה של מופע ממשק באמצעות @Binds
עיינו בדוגמה AnalyticsService
. אם AnalyticsService
הוא ממשק, אי אפשר להחדיר אותו באמצעות ה-constructor. במקום זאת, צריך לספק את 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 }
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
ממשקים הם לא המקרה היחיד שבו אי אפשר להחדיר סוג באמצעות ה-constructor.
בנוסף, לא ניתן לבצע החדרת בנייה אם אתם לא הבעלים של הכיתה, כי היא
מגיע מספרייה חיצונית (כיתות כמו
Retrofit,
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. אבל יכול להיות תצטרכו לבצע החדרת שדה במחלקות שלא נתמכות בהיטים.
במקרים כאלה, אפשר ליצור נקודת כניסה באמצעות @EntryPoint
הערה. נקודת הכניסה היא הגבול בין קוד שמנוהל על ידי Hilt לבין קוד שלא מנוהל על ידו. זו הנקודה שבה הקוד נכנס לראשונה לתרשים האובייקטים שמנוהל על ידי Hilt. נקודות הכניסה מאפשרות ל-Hhilt להשתמש בקוד ש-Hhilt עושה
לא מאפשרות לספק יחסי תלות בתוך תרשים התלות.
לדוגמה, Hilt לא תומך ישירות בספקי תוכן. אם אתם רוצים לראות תוכן
להשתמש ב-Hhilt כדי לקבל יחסי תלות, צריך להגדיר ממשק
שנוסף לו הערות עם @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 and Dagger
Hilt מבוסס על ספריית ההזרקה של יחסי התלות Dagger, ומספק דרך רגילה לשילוב 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 זמין במקורות המידע הנוספים הבאים.
דוגמיות
כך מטמיעים הגדרות מנוהלות, שאפליקציות אחרות יכולות לשנות באותו מכשיר. התכונות הארגוניות של Android מספקות לארגונים פלטפורמת ניידות אחידה של Android — שילוב מכשירים, אפליקציות, וניהול. אפליקציות ל-Android תואמות לתכונות של Android לארגונים כברירת מחדל. אבל יש תכונות נוספות שאפשר להשתמש בהן כדי כדי שהאפליקציה תפעל בצורה יישום שיטות מומלצות יעזור לכם לוודא שהאפליקציות שלכם פועלות בצורה חלקה בסביבה הארגונית.הגדרה של הגדרות מנוהלות
מדריך למפתחים
פרופילים של עבודה
Codelabs
בלוגים
- הזרקת יחסי תלות ב-Android באמצעות Hilt
- קביעת היקף ב-Android ו הכנסה
- הוספת רכיבים להיררכיה של Hilt
- העברת אפליקציית Google I/O ל-Hilt