دگر آسونه قسمت 1(component , @inject@)

یه کلاس Car داریم که که وابسته هست به کلاس Engine یعنی هر ماشین برای ساخته شدن باید یک موتور براش ساخته بشه.فرض کنیم کلاس Car , Engine به این شکل هستن:public class Car { private static final String TAG = &quotCar&quot private Engine engine; public Car(Engine engine) { this.engine = engine; Log.d(TAG, &quotcar created&quot); } public void drive() { Log.d(TAG, &quotdriving&quot); } }public class Engine { public static final String TAG = &quotEngine&quot public Engine() { Log.d(TAG, &quotengine created&quot); } }خب توی حالت عادی برای صدا کردن متد drive در کلاس car باید یک شی از engine بسازیم و اون رو به شی ساخته شده از کلاس car بفرستیم و متد مورد نظر رو صدا کنیم اینجوری:Engine engine = new Engine(); Car car = new Car(engine); car.drive();با استفاده از دگر ما از شر این new کردن ها راحت میشیم دیگه دگر مسئولیت فراهم کردن وابستگی ها و نیازمندی ها رو به عهده میگیره و ما فقط متد مربوطه رو صدا میکنیم برای شروع کار با دگر قبل از کانستراکتور هامون که نیازمندی یه کلاس دیگه هستن و ما قراره ازشون یک شی بسازیم یه انوتیشن inject رو میذاریم تو مثال ما Engine یک نیازمندی برای کلاس Car هست پس قبل از کانستراکتور Engine یک inject قرار میدیم از طرفی برای استفاده از متد های درون Car نیاز هست یک شی هم از Car بسازیم پس یک inject هم برای Car قرار میدیم که کلاسهامون بعد از این تغییرات این شکلی میشن:public class Car { private static final String TAG = &quotCar&quot private Engine engine; @Inject public Car(Engine engine) { this.engine = engine; Log.d(TAG, &quotcar created&quot); } public void drive() { Log.d(TAG, &quotdriving&quot); } }public class Engine { public static final String TAG = &quotEngine&quot @Inject public Engine() { Log.d(TAG, &quotengine created&quot); } }حالا یه اینترفیس باید بسازیم که اونوتیشن component رو داشته باشه بالاسرش حالا کار اینترفیس چیه ؟ فریم ورک دگر برای تولید کدی که نیازمندی های مورد درخواست کلاس را فراهم کنه از این اینترفیس استفاده میکنه کد زیر رو ببینید:@Component public interface AppComponent {}خب حالا باید داخل این اینترفیس یک متد بسازیم که خروجی اون از نوع کلاسی باشه که ما میخوایم ازش شی داشته باشیم خروجی از نوع Car باشه@Component public interface AppComponent { Car getCar(); }حالا یه بار پروژه رو بیلد میکنیم که دگر فایلهای مربوط به خودش رو بسازه توی اکتیویتی ای که هستیم و میخوایم از car استفاده کنیم باید یه شی بسازیم از نوع AppComponent و با استفاده از کلاسی که دگر ساخته اون رو ایجاد کنیم دگر بعد از بیلد کردن یه کلاس برای ما ساخته با اسم DaggerAppComponentکه این کلاس یه متد create داره که وظیفه ش ساخت وابستگی هاس کدمون داخل اکتیویتی این شکلی شده تا الان :AppComponent component = DaggerAppComponent.create();حالا یه شی از کار میسازیم و با استفاده از component اون رو مقدار دهی میکنیم.Car car= component.getCar();حالا با استفاده از car میتونیم متد درایو رو صدا کنیمcar.drive();سه مدل inject داریم :Constructor InjectionField InjectionMethod injectionمورد اول یعنی Constructor Injection رو که بررسی کردیم حالا به تغییراتی که توی کلاس car میدیم نگاه کنید engine رو از داخل کانستراکتور خارج کردیم و بالاسر فیلدش یه inject زدیم public class Car { private static final String TAG = &quotCar&quot @Inject Engine engine; @Inject public Car() { Log.d(TAG, &quotcar created&quot); } public void drive() { Log.d(TAG, &quotdriving&quot); } }اگه برنامه رو ران کنیم میبینم که لاگهایی که داخل Engine هم گذاشتیم ایجاد میشن .توی اکتیویتی میام و car رو هم تبدیل به فیلد میکنم و یه انوتیشن inject بالاسرش قرار میدم توی کلاس AppComponnent میرم یه متد void ایجاد میکنم به نام inject و توی ورودی بهش اکتیویتی رو پاس میدمحالا اگه توی اکتیویتی فقط این متد inject رو صدا بزنیم وقتی برنامه اجرا شه به ترتیب لاگ ساخت Engine و لاگ ساخت Car ایجاد میشن.public class MainActivity extends AppCompatActivity { @Inject Car car; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); AppComponent component = DaggerAppComponent.create(); component.inject(this); }}اینم کلاس AppComponent@Component public interface AppComponent { Car getCar(); void inject (MainActivity activity); } این حالت Field Injection بود .حالا اگه توی کلاس car بالای drive هم یک انوتیشن inject بذاریم موقع اجرا بدون اینکه نیاز باشه این متد رو صدا کنیم کدهای داخل اون هم اجرا میشن که به این حالت Method injection میگیمpublic class Car { private static final String TAG = &quottag Car&quot @Inject Engine engine; @Inject public Car() { Log.d(TAG, &quotcar created&quot); } @Inject public void drive() { Log.d(TAG, &quotdriving&quot); } }یه پروژه ساختم توی این آدرس همه کدهایی که قراره استفاده شه رو توی برنچ های مختلف قرار دادم: https://github.com/ftml71/Dagger