این لایبرری بسیار گسترده است، بنابراین ما توضیحات آن را به دو قسمت تقسیم کرده ایم.
قسمت یک: معرفی کتابخانه dagger 2 و آشنایی با مفهوم تزریق وابستگی
قسمت دو: استفاده از Dagger 2 در یک برنامه ی واقعی
برای درک کاربرد لایبرری Dagger 2 در اندروید، اجازه بدهید اول جواب سوال زیر را بدهیم:
چرا به تزریق وابستگی نیاز داریم؟
تزریق وابستگی برای پیاده سازی مفهوم کنترل و تنظیم کردن از بیرون است که میگوید یک کلاس باید وابستگی هایش را از بیرون دریافت کند. به زبان ساده تر هیچ کلاسی نباید کلاس دیگری را مقدار دهی ( instantiate) کند یا هیچ کلاسی نباید از کلاس دیگری شیء یا نمونه بسازد بلکه باید شیء مورد نیاز خود را از کلاس دیگری که فقط به همین منظور ساخته شده است دریافت کند.
در زبان جاوا، اگر کلاسی خودش از کلاس دیگر با استفاده از کلمه کلیدی new شیء بسازد، سپس این کلاس قابلیت استفاده شدن و تست شدن را به صورت یک کلاس مستقل از دست می دهد و برای درست کار کردن همیشه به کلاس دیگر وابسته است که به این حالت وابستگی سخت میگوییم.
بنابراین مزیت ساخت وابستگی های یک کلاس در بیرون از آن چیست؟
مهمترین مزیت آن این است که امکان استفاده مجدد از کلاس را افزایش می دهد و قادر است به صورت مستقل از دیگر کلاس ها تست شود.
حالا احتمالا مهم ترین سوالی که برایتان پیش آمده است می تواند این باشد که چطور ما وابستگی ها را از بیرون تزریق کنیم؟
برای پاسخ دادن به این سوال کمی زمان را به عقب می بریم:
یک کلاس به عنوان مخزن وابستگی ها برای بررسی وابستگی های سایر کلاس ها مورد استفاده قرار می گرفت و این توانایی را داشت تا شیء های مورد نیاز را بسازد و تزریق کند و برای این کار از Java Reflection استفاده میکرد و به صورت وابستگی های سخت از بین می رفتند و ما به این ترتیب میتوانستیم با استفاده از اشیاء ساخته شده در مخزن وابستگی ها، کلاس ها را به صورت مستقل تست کنیم. این فرایند تزریق وابستگی در Dagger 1 بود.
فرآیندی که توضیح دادیم دو مشکل اصلی داشت: اول اینکه java reflection کند بود و مورد دوم اینکه کلاس ها در زمان اجرا ساخته می شدند و در مخزن وابستگی ها قرار می گرفتند و ما با مشکل اینکه برنامه در زمان اجرا با Crash کند روبرو بودیم.
این مشکلات نسبتا بزرگ باعث شدند که Dagger 2 ساخته بشه.
برزگترین تغییری که در Dagger 2 این بود که گراف وابستگی با استفاده از Annotation Processor ساخته میشد. کلاسی که وابستگی های ما را فراهم می کرد الان در زمان Build شدن برنامه با استفاده از بسته ی javax inject به وجود میاد که باعث میشه ما قبل از اجرای برنامه برای رفع اشکالات احتمالی فرصت داشته باشیم و کلاس هایی که ساخته میشن خیلی خوانا هستن.
نکته: Annotation Processor راهی برای خواندن فایل های کامپایل شده در دوره Build Time است که برای تولید کد استفاده می شود.
حالت های مختلف تزریق وابستگی:
1) Constructor Injection: تزریق پارامتر های متد.
2) Field Injection: تزریق متغیر عضو(نباید به صورت private تعریف شده باشد).
3) Method Injection: تزریق پارامتر های متد.
نکته: فیلد ها و پارامتر های متد ها بعد از فراخوانی سازنده کلاس تزریق می شوند و شما نمیتوانید از آنها در سازنده استفاده کنید.
حالا میخواهم فرآیند تزریق وابستگی یا Dependency Injection را به صورت زیر بیان کنم:
یک درخواست کننده، وابستگی (Object) مورد نیاز خود را از ارائه دهنده ی وابستگی با استفاده از یک واسط درخواست میکند.
ارائه دهنده ی وابستگی: کلاس های که با @Module علامت گذاری شده اند و مسئول ارائه دادن اشیائی هستند که می توانند تزریق شوند. در این کلاس ها متد ها @Provide نشانه گذاری می شوند و نوع برگشتی این متد ها همان آبجکت های مورد نیاز هستند.
مصرف کننده ی وابستگی: نشانه ی @Inject برای تعریف وابستگی استفاده می شود.
اتصال مصرف کننده و ارائه دهنده: یک interface که با استفاده از @Component نشانه گذاری می شود ارتباط بین ارائه دهنده ی اشیاء (@Module) و کلاس هایی که به این اشیاء نیاز دارند را تعریف میکند. کلاسی با استفاده از این interface توسط Dagger برای ما ساخته می شود.
محدودیت های Dagger 2:
1) فیلد های خصوصی(private) را نمی تواند تزریق کند.
2) اگر میخواهید از تزریق فیلد (field injection) استفاده کنید باید یک متد در interfaceی که با @Component علامت گذاری کرده اید تعریف کنید که کلاس نمونه را میگیرد و فیلد مربوطه را تزریق می کند.
منبع: blog.mindorks.com