لوگو عباس اویسی

متولد تهران، توسعه دهنده‌ی اندروید، پیگیر فوتبال. ارشد نرم افزار و علاقمند به جنبه‌های مختلف توسعه‌ی نرم افزار

  • عمومی
  • اندروید
  • جنریتور حلما
  • فریم‌ورک dagger
  • وب‌سرویس آموزشی فیلم‌ها

سه نکته‌ی کاربردی در dagger2 (قسمت دوم)

مرداد ۱۱, ۱۳۹۶

در قسمت قبل نحوه‌ی استفاده از Component.Builder@ و BindsInstance@ رو توضیح دادم، توی این پُست قراره در مورد دو نکته‌ی بعدی بنویسم. اگر میخواید به سورس کامل دسترسی داشته باشید به ریپوی SearchMovies برید.

نکته‌ی دوم- استفاده از متد‌های استاتیک همراه با Provides@

این نکته برای پروژه‌های جاوا خیلی تاثیرگذار نیست ولی به بازدهی پروژه‌های اندروید خیلی کمک میکنه. نکته‌اش خیلی سادس و فقط کافیه متد‌های داخل ماژولتون رو تبدیل به متد‌های استاتیک بکنید (در نظر داشته باشید که اگر متدی رو استاتیک بکنید، دیگه نمیتونه به فیلد‌های غیر استاتیک اون کلاس دسترسی داشته باشه). وقتی متدهارو استاتیک میکنید، دیگه دگر مجبور نیست برای فراخوانی متد‌های کلاس ماژولتون یک object ازش بسازه و میتونه بدون اینکار مستقیما متدهارو صدا بزنه، در نتیجه بازدهی بالاتر میره. بعد تغییر دادن متد‌ها کلاس AndroidModule این شکلی میشه:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Module
public class AndroidModule {
 
    @Provides
    @Singleton
    public static Context provideContext(SearchMovieApplication application) {
        return application.getApplicationContext();
    }
 
    @Provides
    @Singleton
    public static Resources provideResources(SearchMovieApplication application) {
        return application.getResources();
    }
 
    @Provides
    @Singleton
    public static SharedPreferences provideSharedPreferences(SearchMovieApplication application) {
        return PreferenceManager.getDefaultSharedPreferences(application);
    }
 
}

 

نکته‌ی سوم- استفاده از Binds@ به جای Provides@

دگر نمیتونه اینترفیس‌هارو تزریق بکنه، دلیلشم این هست که نمیتونه متوجه بشه شما به object کدوم کلاس (از بین کلاس‌هایی که این اینترفیس رو پیاده سازی کردن) نیاز دارید. پس باید داخل یکی از ماژول‌ها همچین متدی رو بنویسید:

Java
1
2
3
4
@Provides
public MovieInteractor provideMovieInteractor() {
    return new MovieInteractorImpl();
}

اگر سازنده‌ی MovieInteractorImpl نیاز به ورودی داشت، میشه اون‌هارو به عنوان پارامتر ورودی متد نوشت. مثل زیر:

Java
1
2
3
4
@Provides
public MovieInteractor provideMovieInteractor(SearchMoviesApiService searchMoviesApiService, SchedulerProvider scheduler) {
    return new MovieInteractorImpl(searchMoviesApiService,scheduler);
}

مشکل این روش اینه که اگر یه پارامتر به سازنده‌ی MovieInteractorImpl اضافه بشه، باز شما باید بیاید و متد provideMovieInteractor رو تغییر بدید. پس بهترین راه این هست که ساختن MovieInteractorImpl رو به عهد‌ه‌ی دگر بذارید و شما فقط Return بکنیدش. اینجوری:

Java
1
2
3
4
@Provides
public MovieInteractor provideMovieInteractor(MovieInteractorImpl movieInteractorImpl) {
    return movieInteractorImpl;
}

حالا دگر اومده Binds@ رو معرفی کرده و دیگه لازم نیست خودتون متد provideMovieInteractor رو بنویسید. این متد رو باید abstract تعریف کنید و بجای Provides@ از Binds@ استفاده کنید. البته Binds@ قابلیت‌های خوب دیگه‌ای هم داره که فراتر از این پُست هست. متد جدید به شکل زیر میشه:

Java
1
2
   @Binds
    public abstract MovieInteractor provideMovieInteractor(MovieInteractorImpl interactor);

البته بدیهی هست توی این حالت کلاس MovieInteractorImpl باید حتما اینترفیس MovieInteractor رو پیاده سازی کرده باشه وگرنه دگر خطا میده.