אם אתם מפתחים אפליקציות אנדרואיד, סביר להניח שנתקלתם בצורך לארגן טוב יותר את המחלקות שלכם כדי למנוע מהפרויקט להידרדר לכאוס מוחלט. כאן נכנסת לתמונה הזרקת תלויות (dependency injection) , תבנית עיצוב שלמרות שהיא עשויה להיראות בתחילה כמו קסם שחור, היא למעשה דרך לספק לכל מחלקה את האובייקטים שהיא צריכה מבלי שהמחלקה תצטרך ליצור אותם בעצמה.
Hilt מגיע כדי להציל אותנו מהמורכבות של Dagger, ומציע שכבה עליונה שמתקננת את הכנסת התלויות . על ידי אינטגרציה עם Jetpack, Hilt מנהלת אוטומטית קונטיינרים ומחזורי חיים, ומאפשרת לנו להתמקד בלוגיקה עסקית במקום להזיז אובייקטים כאילו אנחנו במעבר דירה.
תצורת סביבה ראשונית
כדי להתחיל עם Hilt, הצעד הראשון הוא להכין את סביבת Gradle. חיוני להוסיף את ה- hilt-android-gradle-plugin לקובץ התצורה ברמת הפרויקט שלך. לאחר מכן, בקובץ המודול של האפליקציה שלך, עליך להחיל את התוסף ולהוסיף את התלויות המתאימות, תוך הקפדה על הגדרת המהדר (בין אם באמצעות kapt או KSP) כהלכה.
פרט חשוב אחד הוא שכדי שהכל יפעל בצורה חלקה, יש להגדיר את הפרויקט לשימוש ב- Java 17 (או Java 8 עבור גרסאות ישנות יותר), שכן זהו תנאי מוקדם לעבודה חלקה בין Hilt ל- Jetpack Compose . אם שמתם לב שהתוכנית לא מתקמפלת כשאתם מפעילים את התוסף, בדקו שוב שגרסאות Kotlin ו-KSP תואמות בדיוק, שכן אפילו פער קל יכול לשבש את כל תהליך הקומפילציה.
לב ליבה של הילט: מחלקת היישומים
כל אפליקציה שרוצה ליהנות מספרייה זו חייבת להיות בעלת מחלקה מותאמת אישית של Application. יצירתה בלבד אינה מספיקה; היא חייבת להיות מסומנת עם ההערה @HiltAndroidApp . שורה זו מפעילה את יצירת הקוד של Hilt ויוצרת את קונטיינר הבסיס של האפליקציה.
רכיב ברמה העליונה הזה חיוני משום שהוא מקשר למחזור החיים הכולל של האפליקציה ומשמש כבסיס לכל שאר הרכיבים לגישה לתלויות המוגדרות ברמה זו. כמובן, אל תשכחו לרשום את המחלקה הזו בקובץ AndroidManifest.xml באמצעות המאפיין name, אחרת Hilt יעבור מבלי לשים לב כלל.
הזרקת תלויות לרכיבי אנדרואיד
לאחר שהאפליקציה מוכנה, נוכל להתחיל להזריק תלויות לפעילויות, פרגמנטים, תצוגות או שירותים. לשם כך, אנו משתמשים ב- @AndroidEntryPoint annotation . זה אומר ל-Hilt שהמחלקה הזו היא נקודת כניסה ושהיא צריכה לייצר רכיב ספציפי עבורה.
כאשר אנו רוצים להשיג תלות ספציפית בתוך פעילות, אנו משתמשים בהזרקת שדות דרך האנוטציה @Inject. חשוב מאוד לזכור ששדות אלה אינם יכולים להיות פרטיים ; אם תנסו להשתמש במודיפיקטור הפרטי, המהדר יזרוק שגיאה ללא היסוס. במקרה של Jetpack Compose, פשוט הוספת האנוטציה לפעילות השורש מאפשרת לנו לגשת ל-ViewModels ישירות בתוך הפונקציות הניתנות להרכבה.
אסטרטגיות להגדרת קשרים
Hilt צריך לדעת כיצד ליצור את האובייקטים שאנו מבקשים. הדרך הישירה ביותר היא הזרקת קונסטרוקטור , שבה אנו ממקמים `@Inject` ממש לפני קונסטרוקטור המחלקה. זה מאפשר ל-Hilt לנתח את הפרמטרים ולקבוע כיצד לספק כל אחת מהתלויות הללו.
עם זאת, ישנם מקרים בהם אין לנו שליטה מלאה על המחלקה, כמו בעת שימוש בספריות חיצוניות כמו Retrofit או OkHttpClient. כאן נכנסים לתמונה מודולי Hilt . מודול הוא מחלקה המסומנות ב-@Module וחייבת לכלול @InstallIn כדי לציין איזה רכיב צריך להכיל את התלות הזו.
- שימוש ב-@Provides: פונקציה זו משמשת כאשר המחלקה היא של צד שלישי או דורשת תבנית בנייה מורכבת. כאן אנו מגדירים פונקציה שמחזירה את המופע הדרוש.
- שימוש ב-@Binds: זוהי האפשרות האידיאלית כאשר אנו רוצים לקשר ממשק למימוש קונקרטי. היא מוגדרת כפונקציה מופשטת שאומרת ל-Hilt: "כאשר מישהו מבקש את הממשק הזה, תן לו את המימוש הזה."
ניהול היקף ומחזור חיים
כברירת מחדל, Hilt יוצר מופע חדש בכל פעם שמבקשים תלויות. עם זאת, לפעמים אנחנו צריכים שאובייקט יישאר זהה לאורך כל חיי האפליקציה או המסך. לשם כך, אנו משתמשים ב- component scopes.
אם נסמן מחלקה עם @Singleton ונתקין אותה ב-SingletonComponent, יהיה לנו מופע גלובלי יחיד. אם אנחנו מעדיפים שהאובייקט קיים רק למשך הפעילות, נשתמש ב- @ActivityScoped בתוך ה-ActivityComponent. חשוב מאוד לא להשתמש יתר על המידה ב-scopes, מכיוון ששמירת אובייקטים בזיכרון למשך זמן רב מדי עלולה להשפיע לרעה על ביצועי האפליקציה.
מקרים מיוחדים ומאפיינים מתאימים
לפעמים אנחנו צריכים להזריק שני מימושים שונים של אותו ממשק. כדי להימנע מעומס על המהדר, אנחנו משתמשים ב- qualifiers . qualifier הוא למעשה ביאור מותאם אישית המשמש לתיוג binding ספציפי, המאפשר לנו להבדיל, למשל, בין לקוח HTTP לאימות לבין לקוח לבקשות כלליות.
יתר על כן, Hilt מפשט את הדברים בעזרת גורמים מוגדרים מראש כמו @ApplicationContext ו-@ActivityContext, מה שמאפשר לנו לקבל את ההקשר של אנדרואיד מבלי שנצטרך להגדיר מודולים באופן ידני. לבסוף, עבור מחלקות ש-Hilt לא תומך בהן באופן טבעי (כגון ContentProviders), נוכל להשתמש ב- @EntryPoint annotation , וליצור גשר ידני לחילוץ תלויות מגרף Hilt. שתפו מידע זה כדי שיותר משתמשים יוכלו ללמוד עליו.