معمولا در اندروید گراف دَگر در کلاس اپلیکیشن زندگی میکند، چون میخواهیم تا وقتی که برنامه در حال اجراست گراف در حافظه باشه.
این طوری گراف به لایف سایکل اَپ وصل میشه. تو این مثال، میخواستیم Application Context در گراف در دسترس باشه. نتیجه مثبت این امر اینه که گراف در دسترس سایر کلاسهای اندروید که میتونن به کانتکست دسترسی داشته باشند هم هست و چون توی تست میتونیم از کلاس اپلیکیشن کاستوم استفاده کنیم، برای تست هم خوبه.
حالا بیایین تا AppComponent رو توی کلاس Application بسازیم.
همانطور که گفتیم، وقتی پروژه رو بیلد میکنیم دگر کلاس DaggerAppComponent
که شامل پیادهسازی گراف AppComponent هست رو میسازه.
از جایی که برای گراف یک فکتوری ساختیم با انوتیشن خاص خودش، اینجا میتونیم متد استاتیک فکتوری از کلاس DaggerAppComponent
رو فراخوانی کنیم.
بعد هم متد create اون رو و applicationContext
رو بعنوان کانتکست بهش ارسال کنیم.
همه این کارهارو با Kotlin lazy initialization کردیم، پس متغیر ایجاد شده immutable هست و هروقت لازم باشه ساخته میشه.
این نمونه ای از گراف که در اینجا ساخته شد، در اکتیوتی به کارمون میاد. تو اکتیویتی از این نمونه استفاده میکنیم تا متد inject اش رو فراخوانی کنیم و اکتیوتی رو به عنوان پارامتر براش بفرستیم.
با این کار اکتیوتی درخواست فیلد اینجکشن خودش را به دگر ارسال میکنه. اکتیوتی به این صورت در میاد:
(application as MyApplication).appComponent.inject(this)
فراخوانی appComponent.inject(this)
فیلدهای کلاس اکتیوتی که با Inject انوتیت شدن رو پر میکنه.
یادآوری:
درخواست اکتیوتی از دَگِر برای تزریق وابستگیهایش را در متد on create قبل از super on create بذارید تا از مشکلات بازیابی فرگمنت جلوگیری بشه.
پروژه رو اجرا کنید.
باگی دیدید؟ بعد از ثبت نام باید وارد صفحه اصلی بشید اما به صفحه لاگین می روید، چون نمونهی یوزرمنیجری که در MainActivity استفاده میشه داره در کلاس اپلیکیشن ساخته میشه اما Registration داره از نمونهای از یوزرمنیجر استفاده میکنه که توسط دَگِر پرواید میشه.
1- اول اکتیویتی MainActivity رو به AppComponent مشابه قبل اضافه کنید.
2- به ویو مدل و وابستگیهاش انوتیشن Inject رو اضافه کنید.
3- در اکتیوتی فیلدهای وابستگی رو پیدا کنید و انوتیشن Inject رو اضافه کنید و خطوط مربوط به تعریف اون فیلد هارو از اکتیوتی حذف کنید.
ما دوباره اسم این متد رو هم inject گذاشتیم چون اسم متد مهم نیست و پارامتر ارسالی مهمه.
1- حالا باید MainActivity رو هم تغییرات بدیم. مثلا یوزر منیجر رو بیاید گلوبال تعریف کنید و قبلش انوتیشن Inject بذارید، برای ویومدل هم همین طور.
2- سپس مقداردهی این دو فیلد رو حذف کنید چون قراره توسط دگر پر بشن.
3- کلاس MainActivity رو در AppComponent اینجکت کنید.
کلاس UserManager همین الان در گراف هست و دَگِر میدونه چطور ازش نمونه بسازه اما در مورد ساخت MainViewModel اطلاع نداره که باید توسط روش Inject سازنده اونو به دگر معرفی کنیم.
همان طور که می بینید MainViewModel به UserDataRepository
وابستگی دارد. پس اونو هم با Inject انوتیت میکنیم:
از جاییکه UserManager
از قبل در گراف بوده، دَگِر تمام اطلاعات لازم برای بیلد موفق گراف در اختیار دارد.
پروژه رو بیلد کنید .
دوباره خطا گرفتید درسته؟
error: Dagger does not support injection into private fields
این خطا به یکی از بدیهای دَگِر مربوط میشه. در هنگام فیلد اینجکشن، این فیلدها نمیتونن private باشن
مودیفایر private رو بردارید و مجدد پروژه رو بیلد کنید.با موفقیت بیلد شد درسته؟ حالا میتونید پروژه رو اجرا کنید.
برای شروع مجدد، دکمه Unregister رو بزنید و دوباره رجیستر کنید. بعد از رجیستر باز هم به صفحه main نرفتید؟ دوباره وارد Login شدید؟پس باز هم باگ داریم !! اما چرا؟! جریان رجیستر و جریان main هردو دارن از UserManager که از گراف اپلیکیشن تزریق شده استفاده میکنند. مشکل اینه که دگر به طور دیفالت همیشه یک نمونه جدید از تایپ ها(در مورد ما UserManager) پرواید میکنه!
آها پس مشکل ساخته شدن مجدد UserManager و از دست رفتن اطلاعات ثبت نامه!
ما باید دگر رو وادار کنیم از همون نمونه قبلی UserManager دوباره استفاده کنه. اما چطور؟
کُدلَب استفاده از دَگِر در برنامه اندرویدی (5-استفاده از Scope)
کُدلَب استفاده از دَگر در برنامه اندرویدی (3-انوتیشنها)
کُدلَب استفاده از دَگِر در برنامه اندرویدی (2-شروع)
کُدلَب استفاده از دَگِر در برنامه اندرویدی(1-معرفی)