سه نکتهی کاربردی در dagger2 (قسمت دوم)
در قسمت قبل نحوهی استفاده از Component.Builder@ و BindsInstance@ رو توضیح دادم، توی این پُست قراره در مورد دو نکتهی بعدی بنویسم. اگر میخواید به سورس کامل دسترسی داشته باشید به ریپوی SearchMovies برید.
نکتهی دوم- استفاده از متدهای استاتیک همراه با Provides@
این نکته برای پروژههای جاوا خیلی تاثیرگذار نیست ولی به بازدهی پروژههای اندروید خیلی کمک میکنه. نکتهاش خیلی سادس و فقط کافیه متدهای داخل ماژولتون رو تبدیل به متدهای استاتیک بکنید (در نظر داشته باشید که اگر متدی رو استاتیک بکنید، دیگه نمیتونه به فیلدهای غیر استاتیک اون کلاس دسترسی داشته باشه). وقتی متدهارو استاتیک میکنید، دیگه دگر مجبور نیست برای فراخوانی متدهای کلاس ماژولتون یک object ازش بسازه و میتونه بدون اینکار مستقیما متدهارو صدا بزنه، در نتیجه بازدهی بالاتر میره. بعد تغییر دادن متدها کلاس AndroidModule این شکلی میشه:
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 کدوم کلاس (از بین کلاسهایی که این اینترفیس رو پیاده سازی کردن) نیاز دارید. پس باید داخل یکی از ماژولها همچین متدی رو بنویسید:
1 2 3 4 |
@Provides public MovieInteractor provideMovieInteractor() { return new MovieInteractorImpl(); } |
اگر سازندهی MovieInteractorImpl نیاز به ورودی داشت، میشه اونهارو به عنوان پارامتر ورودی متد نوشت. مثل زیر:
1 2 3 4 |
@Provides public MovieInteractor provideMovieInteractor(SearchMoviesApiService searchMoviesApiService, SchedulerProvider scheduler) { return new MovieInteractorImpl(searchMoviesApiService,scheduler); } |
مشکل این روش اینه که اگر یه پارامتر به سازندهی MovieInteractorImpl اضافه بشه، باز شما باید بیاید و متد provideMovieInteractor رو تغییر بدید. پس بهترین راه این هست که ساختن MovieInteractorImpl رو به عهدهی دگر بذارید و شما فقط Return بکنیدش. اینجوری:
1 2 3 4 |
@Provides public MovieInteractor provideMovieInteractor(MovieInteractorImpl movieInteractorImpl) { return movieInteractorImpl; } |
حالا دگر اومده Binds@ رو معرفی کرده و دیگه لازم نیست خودتون متد provideMovieInteractor رو بنویسید. این متد رو باید abstract تعریف کنید و بجای Provides@ از Binds@ استفاده کنید. البته Binds@ قابلیتهای خوب دیگهای هم داره که فراتر از این پُست هست. متد جدید به شکل زیر میشه:
1 2 |
@Binds public abstract MovieInteractor provideMovieInteractor(MovieInteractorImpl interactor); |
البته بدیهی هست توی این حالت کلاس MovieInteractorImpl باید حتما اینترفیس MovieInteractor رو پیاده سازی کرده باشه وگرنه دگر خطا میده.