فرشته ناجی
فرشته ناجی
خواندن ۳ دقیقه·۳ سال پیش

کُدلَب استفاده از دَگر در برنامه اندرویدی (4-تزریق گراف به اکتیوتی)

چطور گرافی که ساختیم به اکتیویتی اینجکت کنیم؟

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

این طوری گراف به لایف سایکل اَپ وصل میشه. تو این مثال، می‌خواستیم Application Context در گراف در دسترس باشه. نتیجه مثبت این امر اینه که گراف در دسترس سایر کلاس‌های اندروید که می‌تونن به کانتکست دسترسی داشته باشند هم هست و چون توی تست می‌تونیم از کلاس اپلیکیشن کاستوم استفاده کنیم، برای تست هم خوبه.

حالا بیایین تا AppComponent رو توی کلاس Application بسازیم.

همانطور که گفتیم، وقتی پروژه رو بیلد می‌کنیم دگر کلاس DaggerAppComponentکه شامل پیاده‌سازی گراف AppComponent هست رو می‌سازه.

ساخت نمونه از AppComponent در کلاس اپلیکیشن
ساخت نمونه از AppComponent در کلاس اپلیکیشن

از جایی که برای گراف یک فکتوری ساختیم با انوتیشن خاص خودش، اینجا می‌تونیم متد استاتیک فکتوری از کلاس DaggerAppComponentرو فراخوانی کنیم.

بعد هم متد create اون رو و applicationContextرو بعنوان کانتکست بهش ارسال کنیم.

همه این کارهارو با Kotlin lazy initialization کردیم، پس متغیر ایجاد شده immutable هست و هروقت لازم باشه ساخته می‌شه.

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

با این کار اکتیوتی درخواست فیلد اینجکشن خودش را به دگر ارسال می‌کنه. اکتیوتی به این صورت در میاد:

درخواست تزریق به دگر توسط اکتیویتی
درخواست تزریق به دگر توسط اکتیویتی

تغییرات:

  • قبل از تعریف ویو مدل @Inject میاد.
  • خط زیر به متد on create و قبل از فراخوانی super اضافه میشه.
(application as MyApplication).appComponent.inject(this)
  • خط مربوط به ساخت ویومدل حذف میشه.
فراخوانی appComponent.inject(this)فیلدهای کلاس اکتیوتی که با Inject انوتیت شدن رو پر می‌کنه.


یادآوری:

درخواست اکتیوتی از دَگِر برای تزریق وابستگی‌هایش را در متد on create قبل از super on create بذارید تا از مشکلات بازیابی فرگمنت جلوگیری بشه.

پروژه رو اجرا کنید.

باگی دیدید؟ بعد از ثبت نام باید وارد صفحه اصلی بشید اما به صفحه لاگین می روید، چون نمونه‌ی یوزرمنیجری که در MainActivity استفاده میشه داره در کلاس اپلیکیشن ساخته میشه اما Registration داره از نمونه‌ای از یوزرمنیجر استفاده می‌کنه که توسط دَگِر پرواید می‌شه.


افزودن Main flow به دَگِر

1- اول اکتیویتی MainActivity رو به AppComponent مشابه قبل اضافه کنید.

2- به ویو مدل و وابستگی‌هاش انوتیشن Inject رو اضافه کنید.

3- در اکتیوتی فیلدهای وابستگی رو پیدا کنید و انوتیشن Inject رو اضافه کنید و خطوط مربوط به تعریف اون فیلد هارو از اکتیوتی حذف کنید.

افزودن متد اینجکت MainActivity به AppComponent
افزودن متد اینجکت MainActivity به AppComponent


ما دوباره اسم این متد رو هم 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 دوباره استفاده کنه. اما چطور؟

با Scoping !

بعدی

کُدلَب استفاده از دَگِر در برنامه اندرویدی (5-استفاده از Scope)

قبلی

کُدلَب استفاده از دَگر در برنامه اندرویدی (3-انوتیشن‌ها)

کُدلَب استفاده از دَگِر در برنامه اندرویدی (2-شروع)

کُدلَب استفاده از دَگِر در برنامه اندرویدی(1-معرفی)


تزریق وابستگیدگرکاتلیناندرویدdependency injection
برنامه نویس اندروید @NeshanMap
شاید از این پست‌ها خوشتان بیاید