בפרויקט עם 50+ שירותים ו-repositories, רישום ידני של תלויות דרך GetIt הופך לכאוס. injection_container.dart תופח ל-500+ שורות, סדר הרישום מתערבב, ובמהלך רפקטורינג מפתחים שוכחים לעדכן את הרישומים. התוצאה: StateError: No instance of type ApiService found בזמן ריצה. נתקלנו בזה עשרות פעמים ולמדנו לפתור את הבעיה אוטומטית. בפרויקט אחד, רישום ידני לקח עד 3 ימי עבודה עבור כל תכונה חדשה.
הגדרת injectable — מחולל קוד על גבי GetIt — מפחיתה קוד ידני ב-70% ומבטלת שגיאות רישום. פשוט כותבים @injectable או @lazySingleton annotations, מריצים build_runner, וזה מייצר את קובץ injection.config.dart. זהו זה — DI הופך לנקי והצהרתי. זה מוריד את מאמץ התחזוקה בעד 80%.
איך injectable מפשטת ניהול תלויות
רישום ידני ב-GetIt לא מתאים לקנה מידה גדול: עם 50+ תלויות קל לאבד את הסדר, לשכוח לעדכן במהלך רפקטורינג, וה-injection_container של מישהו אחר הופך לעיתים קרובות למעין קופסה שחורה. injectable מבטלת את העבודה הידנית הזו — הוסף annotation למחלקה שלך, הרץ build_runner, והקובץ מתעדכן אוטומטית. חיסכון בזמן: עד שעתיים בשבוע על תחזוקת DI. בפועל, זה אומר שמפתחים מבלים פחות זמן במשימות שגרתיות ועושים פחות טעויות.
איך להגדיר injectable בפרויקט
ההגדרה הבסיסית אורכת 10-15 דקות. הוסף תלויות ל-pubspec.yaml:
dependencies: get_it: ^7.6.0 injectable: ^2.3.0 dev_dependencies: injectable_generator: ^2.4.0 build_runner: ^2.4.0 צור נקודת כניסה — קובץ עם פונקציית אתחול:
import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';
import 'injection.config.dart';
final sl = GetIt.instance;
@InjectableInit()
Future<void> configureDependencies() => sl.init();הוסף annotation לשירות שלך, לדוגמה:
@lazySingleton class ApiService { final Dio _dio; ApiService(this._dio); } הרץ את ה-generation: dependencies: get_it: ^7.6.0 injectable: ^2.3.0 dev_dependencies: injectable_generator: ^2.4.0 build_runner: ^2.4.0 . ל-generation רציף השתמש ב-import 'package:get_it/get_it.dart'; import 'package:injectable/injectable.dart'; import 'injection.config.dart'; final sl = GetIt.instance; @InjectableInit() Future<void> configureDependencies() => sl.init(); — הוא מעדכן קוד אוטומטית בכל שינוי ב-annotation.
איך לעבוד עם סביבות
@lazySingleton class ApiService { final Dio _dio; ApiService(this._dio); } תומכת ב-dart run build_runner build --delete-conflicting-outputs annotations — תמיכה מובנית ל-dev, staging, production ללא תנאים ידניים. דוגמה:
@dev
@LazySingleton(as: ApiService)
class MockApiService implements ApiService {
...
}
@prod
@LazySingleton(as: ApiService)
class RealApiService implements ApiService {
...
}
// Инициализация с окружением:
await configureDependencies(environment: Environment.prod);בבדיקות העבר build_runner watch — mocks מחוברים אוטומטית. אין הצהרות injectable במיכל ההזרקה.
איך לטפל בתלויות אסינכרוניות
לאתחול אסינכרוני השתמש ב-@Environment:
@singleton
class DatabaseService {
late final Database _db;
@factoryMethod
static Future<DatabaseService> create() async {
final service = DatabaseService();
service._db = await openDatabase('app.db');
return service;
}
}@dev @LazySingleton(as: ApiService) class MockApiService implements ApiService { ... } @prod @LazySingleton(as: ApiService) class RealApiService implements ApiService { ... } // Инициализация с окружением: await configureDependencies(environment: Environment.prod); מייצרת Environment.dev, ו-if מחזירה injection_container. אל תשכח @factoryMethod לפני @singleton class DatabaseService { late final Database _db; @factoryMethod static Future<DatabaseService> create() async { final service = DatabaseService(); service._db = await openDatabase('app.db'); return service; } } .
למה מתרחשת שגיאת 'No instance of type'?
הסיבה הנפוצה ביותר: מפתח הוסיף מחלקה חדשה עם annotation אבל שכח להריץ injectable. האפליקציה מתקמפלת עם registerSingletonAsync הישן, והמחלקה החדשה נשארת לא רשומה. פתרון: כלול את configureDependencies() בתהליך הפיתוח שלך או הגדר שלב CI כדי לוודא שהקוד שנוצר מעודכן.
טיפ לפיתוח מהיר יותר
הרץ `build_runner watch` בטרמינל נפרד. זה מייצר קוד מחדש אוטומטית כשקבצים עם annotations משתנים. זה חוסך זמן ומונע שגיאות.השוואה: GetIt ידני לעומת Injectable
| פרמטר | GetIt ידני | Injectable |
|---|---|---|
| נפח קוד | קובץ אחד עם 300+ שורות | ~10 שורות + annotations |
| סיכון לשגיאות רישום | גבוה (הסדר נשכח) | נמוך (יצירת קוד) |
| תמיכה בסביבות | לוגיקה ידנית | מובנית דרך Future |
| רפקטורינג | צריך לערוך את await |
רק לשנות את ה-annotation |
| בדיקות | mocks ידניים נוספים | מעבר קל בין סביבות |
שגיאות DI נפוצות והפתרונות שלהן
| שגיאה | סיבה | פתרון |
|---|---|---|
| No instance of type | build_runner לא הורץ | הרץ build_runner או watch |
| רישום כפול | אותו סוג נרשם פעמיים | השתמש ב-@singleton או @lazySingleton |
| תלות מעגלית | ארכיטקטורה שגויה | פצל שירותים, השתמש ב-factories |
| חוסר התאמה בסביבה | סביבה שגויה | ציין Environment במהלך האתחול |
איך אנחנו מגדירים DI בפרויקט שלך
הגדרת Dependency Injection היא חלק מהארכיטקטורה הסטנדרטית שלנו לפרויקטי Flutter. אנחנו מטפלים בזה turnkey: מתקינים ומגדירים תלויות (get_it, injectable, build_runner), יוצרים נקודת כניסה עם תמיכה בסביבות, מוסיפים annotations לכל השירותים, ה-repositories וה-factories, מגדירים תלויות אסינכרוניות ומתודות factory, משלבים יצירת קוד ב-CI/CD (הרצה אוטומטית של build_runner), מעבירים מיכלי הזרקה ידניים קיימים ל-annotations, ומתעדים את ארכיטקטורת ה-DI. לאחר ההגדרה, הצוות שלך מקבל מבנה ברור שקל להרחיב כשהוספת תכונות חדשות. מפתח חדש יכול להבין את שכבת ה-DI ב-30 דקות במקום כמה שעות.
הניסיון שלנו: 5+ שנים בפיתוח Flutter, מעל 30 פרויקטים ניידים שהושלמו. אנחנו מבטיחים שכבת DI יציבה וניתנת להרחבה בקלות. צור קשר כדי לדון במשימה שלך ולקבל ייעוץ על הארכיטקטורה של האפליקציה שלך. הזמן הגדרת DI — נמצא את הפתרון האופטימלי לפרויקט שלך.
העבודה אורכת 1-3 ימים בהתאם לגודל הפרויקט. לפרויקט חדש זה מהיר יותר; לפרויקט קיים עם DI ידני זה לוקח יותר זמן בגלל הגירה ואימות של סדר הרישום. תוצאה: ארכיטקטורת DI נקייה וניתנת להרחבה. נבחן את הפרויקט שלך — פשוט צור קשר.
תיעוד רשמי של Injectable: pub.dev/packages/injectable







