<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dagger &#8211; Mahdi Tajik</title>
	<atom:link href="http://www.mahditajik.ir/tag/dagger/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.mahditajik.ir</link>
	<description>I&#039;m Mahdi Tajik. I am project manager and Full-stack Android developer. welcome to my personal website.</description>
	<lastBuildDate>Thu, 29 Nov 2018 14:20:09 +0000</lastBuildDate>
	<language>fa-IR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.2.6</generator>

<image>
	<url>http://www.mahditajik.ir/wp-content/uploads/2015/03/cropped-sample-logo-MT-2-32x32.png</url>
	<title>Dagger &#8211; Mahdi Tajik</title>
	<link>http://www.mahditajik.ir</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>کار با Dagger2 به زبان ساده  بخش دوم (پیشرفته)</title>
		<link>http://www.mahditajik.ir/dagger2-advanced-example/</link>
					<comments>http://www.mahditajik.ir/dagger2-advanced-example/#comments</comments>
		
		<dc:creator><![CDATA[mahdi]]></dc:creator>
		<pubDate>Sat, 01 Jul 2017 15:30:09 +0000</pubDate>
				<category><![CDATA[آموزش]]></category>
		<category><![CDATA[annotation]]></category>
		<category><![CDATA[Dagger]]></category>
		<guid isPermaLink="false">http://www.mahditajik.ir/?p=2249</guid>

					<description><![CDATA[<p>سلام دوستان عزیز، متاسفانه کمی طول کشید تا مطلب آموزشی بگذارم، کامنت ها و استقبال شما انرژی خاصی به من داد تا هرچه زود تر نسبت به کامل کردن این بحث اقدام کنم. خیلی خوب، در مقاله قبلی با نحوه استفاده از Dagger2 آشنا شدیم. در این بخش می خواهیم چند روش دیگر استفاده را ...</p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/dagger2-advanced-example/">کار با Dagger2 به زبان ساده  بخش دوم (پیشرفته)</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></description>
										<content:encoded><![CDATA[<p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2424" src="http://www.mahditajik.ir/wp-content/uploads/2017/07/dagger2_2.jpg" alt="" width="800" height="486" srcset="http://www.mahditajik.ir/wp-content/uploads/2017/07/dagger2_2.jpg 800w, http://www.mahditajik.ir/wp-content/uploads/2017/07/dagger2_2-300x182.jpg 300w, http://www.mahditajik.ir/wp-content/uploads/2017/07/dagger2_2-768x467.jpg 768w" sizes="(max-width: 800px) 100vw, 800px" /></p>
<p style="text-align: justify;">سلام دوستان عزیز، متاسفانه کمی طول کشید تا مطلب آموزشی بگذارم، کامنت ها و استقبال شما انرژی خاصی به من داد تا هرچه زود تر نسبت به کامل کردن این بحث اقدام کنم. خیلی خوب، در <span class="highlight"><a href="http://www.mahditajik.ir/dagger2-simple-example/" target="_blank" rel="noopener"><strong>مقاله قبلی</strong></a></span> با نحوه استفاده از Dagger2 آشنا شدیم. در این بخش می خواهیم چند روش دیگر استفاده را به همراه امکانات بیشتر این کتابخانه مورد برسی قرار دهیم. همانطور که در آموزش قبلی به روز کردم به علت استفاده زیاد از این کتابخانه، گوگل امکان اضافه کردن آن را به صورت مستقیم داده و شما می توانید ازین پس بصورت زیر در gradle در سطح خود برنامه از آن استفاده کنید:</p>
<pre class="crayon-plain-tag">compile 'com.google.dagger:dagger:2.7'
annotationProcessor 'com.google.dagger:dagger-compiler:2.7'</pre>
<p style="text-align: justify;">می خواهیم کمی بیشتر با DI آشنا شویم و ابزار های آن را در Dagger2 ببینیم. ما چند نوع تزریق داریم.</p>
<h4 id="constructor-injection"><strong>Constructor injection</strong></h4>
<p>برروی کانستراکتور Inject@ گذاشته و در این صورت دیگر نیازی به نوشتن Module نداریم.</p>
<h4 id="fields-injection"><strong>Fields injection</strong></h4>
<p>همینطور که در آموزش قبل ملاحظه کردید تزریق یک فیلد را گویند. ( در تمامی آموزش قبل از fields injection استفاده کردیم)</p>
<h4 id="methods-injection"><strong>Methods injection</strong></h4>
<p>بروری یک متدی از یک کلاس Inject@ بگذاریم.</p>
<p>&nbsp;</p>
<p><span style="color: #99cc00;"><strong>چند انوتیشن که باید در این جلسه با آنها آشنا شویم:</strong></span><br />
<pre class="crayon-plain-tag">@Scope annotation</pre>
<p style="text-align: justify;">اصولا هدف استفاده از این انوتیشن معرفی <strong>Scope</strong> آبجک تولید شده است. یعنی <strong>Dagger2</strong> به شما این امکان را می دهد تا <strong>Object</strong> های شما چرخه عمر متفاوت داشته باشند و شما فقط تعریف می کنید، مدیریتش با خود <strong>Dagger</strong> است. پیشنهاد من این است که برای این مقاله تا همین حد کافی است و بعد از اتمام این اموزش به <span class="highlight"><a href="http://www.mahditajik.ir/dagger2-custom-scopes/" target="_blank" rel="noopener">مقاله کامل</a></span> مراجعه کنید.</p>
<pre class="crayon-plain-tag">@Qualifier</pre>
<p style="text-align: justify;">وقتی از این انوتیشن استفاده می کنیم که متد ها همنام و و ورودی خروجی یکسان داشته باشند و به <strong>Dagger</strong> می فهمانیم کِی، چی را تزریق کند.</p>
<p style="text-align: justify;">بسیار عالی. در آموزش قبل دیدیم که هرجا بخواهیم از <strong>DI</strong> توسط <strong>Dagger2</strong> استفاده کنیم باید سه مرحله زیر را انجام دهیم:</p>
<p style="text-align: justify;">۱- ساخت <strong>Provider</strong> ها در کلاس <strong>Module</strong> که مشخص می کنیم کلاس ها چگونه تولید شوند.</p>
<p style="text-align: justify;">۲- ساخت اینترفیسی به نام <strong>Component</strong> که می گویم از کدام <strong>Module</strong> ها استفاده کند و متدی در آن قرار می دادیم که کلاسی که در آن <strong>Inject</strong> انجام شده بود وجود داشته باشد تا <strong>Dagger2</strong> بفهمد کدام کلاس ها را جهت فیلد انجکشن اسکن و وایراپ کند و متوجه شدیم که <strong>Dagger</strong> متدها رو بصورت خودکار تولید می کند.</p>
<p style="text-align: justify;">۳- در کلاس استفاده کننده ( قرار است <strong>Inject</strong> اتفاق بیافتد) متد تعریف شده در <strong>Component</strong> را از کلاس <strong>AutoGenerated</strong> توسط <strong>Dagger</strong> صدا بزنیم و  تمام!</p>
<p style="text-align: justify;">اگر هنوز بخش مبهمی مانده با در نظر گرفتن سه مرحله بالا<span style="color: #3366ff;"> <a href="http://www.mahditajik.ir/dagger2-simple-example/" target="_blank" rel="noopener"><strong>آموزش قبل</strong> </a></span>را دوباره مطالعه کنید.</p>
<p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2378" src="http://www.mahditajik.ir/wp-content/uploads/2017/06/dagger_general.png" alt="" width="790" height="636" srcset="http://www.mahditajik.ir/wp-content/uploads/2017/06/dagger_general.png 790w, http://www.mahditajik.ir/wp-content/uploads/2017/06/dagger_general-300x242.png 300w, http://www.mahditajik.ir/wp-content/uploads/2017/06/dagger_general-768x618.png 768w" sizes="(max-width: 790px) 100vw, 790px" /></p>
<p><span style="color: #99cc00;"><strong>حال یک سوال:</strong></span></p>
<p style="text-align: justify;">با توجه به مطالب یاد شده می توانیم هر بخش از برنامه را بصورت <strong>DI</strong> توسط <strong>Dagger2</strong> بنویسیم. مثلا یکسری کلاس هایی را بصورت <strong>Inject</strong> در کلاس های دیگر استفاده کنید. اما سوال من این است که اگر بخواهیم در کل پروژه از <strong>DI</strong> استفاده کنیم چه باید کرد؟ یعنی کلاس هایی که به همدیگر ربط پیدا می کنند. (مثلا <strong>Context</strong> که در خیلی جاها لازم داریم و یا <strong>SharedPrefrence</strong> و یا خیلی کلاس های دیگر) این سوالی بود که برای خودم هم پیش آمد و بهترین جواب برای آن طراحی از بالا به پایین کل پروژه است! یعنی به جای اینکه بیاییم  از پایین به بالا برای تک تک کلاس های استفاده شده <strong>Module</strong> بنویسیم و سپس برسیم به سطح کامپوننت های اندروید مثل <strong>fragment</strong> و <strong>Activity</strong> که واقعاً نشدنی است و ارتباطات خیلی پیچیده می شود و از طرفی <strong>Inject</strong> های تکراری ایجاد می شد که <strong>Dagger2</strong> آن را قبول نمی کند، بهتر است از سطح <strong>Application</strong> به پایین طراحی کنیم. این نکته را هم در نظر داشته باشید که <strong>Dagger2</strong> در یک <strong>DI</strong> مجزا، امکان ساخت یک کامپوننت اصلی را می دهد ( به شکل بالا توجه کنید) و اگر کامپوننت های دیگری داشتیم باید در ارتباط با کامپوننت اصلی باشند.  ( این ارتباط یا از نوع <span style="color: #00ccff;"><strong>Dependency</strong></span> است یا <span style="color: #00ccff;"><strong>SubComponent</strong> </span>که در انتهای این بحث به تفاوت آنها اشاره خواهم کرد.) البته این مساله در صورتی است که <strong>Dependency Injection</strong> های مرتبط به هم داشته باشید. اما اگر فقط می خواهید در بخش های خاصی از برنامه از <strong>DI</strong> استفاده کنید که به هم مرتبط نیستند هر کدام <strong>Component</strong> و <strong>Module</strong> مستقل از هم را خواهند داشت که مشکلی هم پیش نمیاید. مثلا در مساله آموزش قبل که DI را برای تولید خودرو استفاده کردیم، فرض کنید یک <strong>DI</strong> هم برای قایق یا کشتی بنویسیم که بخواهیم تولید قایق را برایمان مدیریت کند. برای این کار دقیقاً مانند <strong>DI</strong> خودرو <strong>Module</strong> و <strong>Component</strong> مربوطه آن را تشکیل می دهیم و ربطی هم به <strong>DI</strong> خودرو ندارد و از هم مستقل اند. تنها نقطه مشترک کلاسی هست که استفاده کننده است. ( مانند <strong>Activity</strong>)</p>
<p>&nbsp;</p>
<p style="text-align: justify;">می خواهیم مثالی ساده نوشته و  آن را باهم برسی کنیم. لطفاً به این بخش خیلی توجه کنید. به علت ارتباط بخش های مختلف ممکن است پیچیدگی ظاهری داشته باشد، اما واقعاً پیچیده نیست و تمامی قوانینی که در جلسه قبل گفتیم صادق است. تلاش من این است که تمامی حالت های ممکن برای ساخت <strong>DI</strong> را برسی کنیم تا تمامی سوالات برطرف شود.</p>
<p><span style="color: #99cc00;"><strong>شرح برنامه:</strong></span></p>
<p style="text-align: justify;">برنامه ای داریم که با استفاده از اطلاعات کاربری، درخواستی به وب زده و نتیجه را در پایگاه داده ذخیره می کند. توجه کنید که اتفاقات بصورت شماتیک است و هدف برسی روابط آنها در <strong>Dagger2</strong> می باشد و صرفاً به ازای اکثر عملیات ها در کد، فقط لاگ کرده ایم. به شکل زیر دقت کنید: کلاس اپلیکیشن دارای کلاس های <strong>Context</strong> و <strong>User</strong> و <strong>Database</strong> (که وابسته به Context  و User است) و <strong>Activity</strong> است و خود کلاس Activity هم شامل NetworkCalss است که  وابسته به <strong>User </strong>است.</p>
<p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2382" src="http://www.mahditajik.ir/wp-content/uploads/2017/07/photo_2017-07-01_12-23-49.jpg" alt="" width="1280" height="800" srcset="http://www.mahditajik.ir/wp-content/uploads/2017/07/photo_2017-07-01_12-23-49.jpg 1280w, http://www.mahditajik.ir/wp-content/uploads/2017/07/photo_2017-07-01_12-23-49-300x188.jpg 300w, http://www.mahditajik.ir/wp-content/uploads/2017/07/photo_2017-07-01_12-23-49-768x480.jpg 768w, http://www.mahditajik.ir/wp-content/uploads/2017/07/photo_2017-07-01_12-23-49-1024x640.jpg 1024w" sizes="(max-width: 1280px) 100vw, 1280px" /></p>
<p><span style="color: #99cc00;"><strong>نکات برنامه:</strong></span></p>
<p style="text-align: justify;">کلاس <strong>Application</strong> به <strong>Database</strong> نیاز دارد تا آن را در اول برنامه <strong>Initilize</strong> کند از طرفی <strong>Database</strong> به <strong>User</strong> و <strong>Context</strong> نیاز دارد. سپس <strong>Activity</strong> یک <strong>Network Request</strong> می زند و نتیجه را در <strong>Database</strong> ذخیره می کند.اول از همه <strong>Module</strong> های مربوط به <strong>User</strong> و <strong>Database</strong> را ایجاد می کنیم تا <strong>Dagger</strong> بفهمد آنها را چگونه تولید کند.</p>
<pre class="crayon-plain-tag">@Module
public class UserModule {

    @Provides
    @Singleton
    User providesUser() {
        return new User("Farhad", "Majidi");
    }
}

@Module
public class DatabaseModule {

    @Singleton
    @Provides
    Database providesDatabase(Context context,User user){
        return new Database(context,user);
    }
}

@Singleton
@Component(modules = {ApplicationModule.class, DatabaseModule.class,UserModule.class})
public interface ApplicationComponent {

    void inject(DaggerTestApplication application);


    // Exported for child-components. (subcomponent need this to use Context or User or Database)

    Context getContext();

    User provideUser();

    Database provideDatabase();

}</pre>
<img decoding="async" loading="lazy" class=" wp-image-2394 alignright" src="http://www.mahditajik.ir/wp-content/uploads/2017/07/simple.jpg" alt="" width="144" height="48" /></p>
<p style="text-align: justify;"><span style="color: #ff9900;">سوال: چه چیزی را می خواهیم تزریق کنیم؟</span> جواب: <strong>DataBase</strong> و <strong>User</strong></p>
<p style="text-align: justify;"><span style="color: #ff9900;">سوال: چطور ساخته می شود؟</span> جواب: در <strong>UserModule </strong> و <strong>DatabaseModule</strong> مشخص شده است و آنها را به عنوان <strong>Module</strong> به <strong>Component</strong> داده ایم!</p>
<p style="text-align: justify;"><span style="color: #ff9900;">سوال: استفاده کننده نهایی کیست؟</span> جواب: <strong>DaggerTestApplication </strong> است بنابر این یک متد با ورودی خودش نوشتیم تا Inject@ های روی فیلدهایش اسکن شود.</p>
<p style="text-align: justify;"><span style="color: #ff9900;">سوال: دوسه تا متد بعدی چیه؟</span> جواب: باید برای هر کلاسی که child ها به آن نیاز دارند یک متد Exporter  بنویسیم.</p>
<p style="text-align: justify;">از آنجایی که می خواهم کلاس <strong>NetworkClass</strong> را فقط در <strong>Activity</strong> استفاده کنم و از طرفی <strong>NetworkClass</strong> به User نیاز دارد بنابراین یک کامپوننت جدا با <strong>Scope</strong> جدید می نویسیم. چون می خواهم مادامی که Activity وجود دارد <strong>NetworkClass</strong> نیز وجود داشته باشد. اما لازم است تا <strong>Component</strong> اصلی متدهایی داشته باشند تا کلاس <strong>User</strong> را برایم <strong>Export</strong> کنند. بنابر این من متدی اضافه کردم به نام <strong>provideUser </strong>که خروجی آن<strong> User </strong>است. خود <strong>Dagger</strong> پیداده سازی آن را مدیریت می کند. همچنین چون ممکن است <strong>Context</strong> برنامه را کلاس های دیگر بخواهند یک متد نیز برای آن نوشتیم و همچنین برای <strong>Database</strong> هم یک متد <strong>Export</strong> کننده نوشتم.( خواهید دید که <strong>DataBase</strong> در <strong>Activity</strong> جهت ذخیره مورد نیاز قرار خواهد گرفت. پس یک متد <strong>Export</strong> کننده لازم داشت.) این طراحی بالا به پایینی بود که اول مقاله گفتم. یعنی در <strong>Component</strong> اصلی که نحوه ارتباط ها را مشخص می کنیم برای فرزند ها نیز وابستگی های مشترک را در نظر بگیریم.</p>
<p style="text-align: justify;">یک نکته دیگر در مورد context است. از آنجایی که کلاس های دیگری ممکن است به آن وابسته شوند یک متد برای آن نوشتیم، اما چون Context را ما نمی سازیم و خود سیستم تولید می کند لازم نیست برایش Module بنویسیم و ساخت و Handle آن توسط خود Dagger با Android system انجام می شود. البته در این پروژه استفاده ای از آن نکردیم، اما مطمئناً به آن نیاز پیدا خواهید کرد.</p>
<p style="text-align: justify;">حال می رویم سراغ وابستگی های <strong>Activity</strong> و این بخش است که کمی برایمان تازگی دارد.</p>
<pre class="crayon-plain-tag">@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}


@Module
public class ServiceModule {

    @ActivityScope
    @Provides
    NetworkClass providesNetworkClass(User user) {
        return new NetworkClass(user);
    }
}

@ActivityScope
@Component(dependencies = ApplicationComponent.class, modules = ServiceModule.class)
public interface ActivityComponent {

    void inject(MainActivity activity);

}</pre>
<strong><img decoding="async" loading="lazy" class="alignright wp-image-2394 " src="http://www.mahditajik.ir/wp-content/uploads/2017/07/simple-300x100.jpg" alt="" width="156" height="52" /></strong></p>
<p style="text-align: justify;"><span style="color: #ff9900;">سوال: چه چیزی را می خواهیم تزریق کنیم؟</span> جواب: <strong>NetworkClass</strong></p>
<p style="text-align: justify;"><span style="color: #ff9900;">سوال: چطور ساخته می شود؟</span> جواب: در <strong>ServiceModule</strong> مشخص شده است و آن را به عنوان <strong>Module</strong> به <strong>Component</strong> داده ایم!</p>
<p style="text-align: justify;"><span style="color: #ff9900;">سوال: اما نحوه ساخت یوزر را در ServiceModule  نداریم؟!</span> جواب: در <strong>ActivityComponent </strong> مشخص کردیم که</p>
<p style="text-align: justify;"><strong>dependencies = ApplicationComponent.class</strong> ( یعنی وابستگی به <strong>ApplicationComponent</strong> داریم و هر کلاسی که در آن <strong>Export</strong> شده است را می توانیم استفاده کنیم. پس <strong>ServiceModule</strong> در ساخت <strong>NetworkClass</strong> یک <strong>User</strong> به عنوان ورودی می گیرد، و نحوه ساخت آن یوزر را <strong>ApplicationComponent </strong> می داند.</p>
<p style="text-align: justify;"><span style="color: #ff9900;">سوال: چرا Scope جدید دادیم؟</span> جواب: برای اینکه می خواهیم مادامی که استفاده کننده آن (Activity ) وجود دارد، <strong>NetworkClass</strong> ما وجود داشته باشد. نحوه دقیق کار Scope <span class="highlight"> <a href="http://www.mahditajik.ir/dagger2-custom-scopes/" target="_blank" rel="noopener">در این آموزش</a></span> موجود است.</p>
<p style="text-align: justify;"><span style="color: #ff9900;">سوال: این NetworkClass کجا استفاده می شود و Dagger از کجا می فهمد؟</span> جواب: این جواب رو دیگه شما هم می دانید و همانطور که در کلاس <strong>Activity</strong> ملاحظه می کنید چون درون دوتا فیلد اینجکشن داریم ( یکی <strong>NetworkClass</strong> و دیگری <strong>DataBase</strong>)  بنابر این یک متدی در <strong>Component</strong> قرار دادم تا ورودی آن از جنس <strong>MainActivity</strong> باشد تا تمامی Field injection های آن اسکن شود و ارتباط ها برقرار شود.</p>
<pre class="crayon-plain-tag">public class MainActivity extends AppCompatActivity {

 
    @Inject
    NetworkClass networkClass;

    @Inject
    Database database;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initialize();
        webRequest();

    }

    private void webRequest() {

        networkClass.request("https://google.com");
        database.saveToDB();
    }

    private void initialize() {

        ((DaggerTestApplication)getApplicationContext()).getActivityComponent().inject(this);
    }


}</pre>
<p style="text-align: justify;">ملاحظه خواهید کرد که هم <strong>NetworkClass</strong> و هم <strong>DataBase</strong> به درستی در <strong>Activity</strong> تزریق شده اند و قابل استفاده هستند. حالا که نحوه کار با <strong>Dagger2</strong> را متوجه شدیم می توانیم برای متوجه شدن بیشتر این کد را به چند صورت متفاوت نوشت و تغییر داد. که همه اینها در <strong>Github</strong> در شاخه های با نام های:<span style="color: #000000;">lesson2, lesson2-type2, lesson2-type3, lesson2-subcomponent</span> قرار گرفته اند.</p>
<p>&nbsp;</p>
<p><span style="color: #99cc00;"><strong>روش های دیگر برای درک کامل</strong></span></p>
<p style="text-align: justify;">برای اینکه دقیقاً بفهمید Dagger2 چطور کار می کند حتماً این مثال ها را ببینید و درک کنید. <span class="highlight">در این چند مثال انواع روش های پیاده سازی را انجام داده ام و فهمیدن انها باعث از بین رفتن گنگی نسبی قضیه و تسلط کامل خواهد شد و جواب بسیاری از سوال هایی که در ذهن دارید را خواهید یافت</span>. تلاشم تغییر روی یک کلاس واحد Database بود تا با ثابت بودن آن تغییر روش ها را ملاحظه نمایید.</p>
<p style="text-align: justify;"><span style="color: #00ccff;">شاخه lesson2 :</span> همین کدی است که در این آموزش داشتیم.</p>
<p style="text-align: justify;"><span style="color: #00ccff;">شاخه lesson2-type2</span> :در کلاس Database خود User تزریق شده است. بنابراین ناچاریم تا متدی بنویسیم که ورودی آن Database باشد تا فیلد های تزریق شده اسکن شود.</p>
<p style="text-align: justify;"><span style="color: #ff0000;"><span style="color: #00ccff;">شاخه lesson2-type3:</span> <span style="color: #000000;">در کلاس Database از Constructor Injection استفاده کردم. همانطور که در تعریف اول بحث مطرح کردم در این روش Inject@ در روی Constructor  کلاس می گذاریم و دیگر نیازی به نوشتن Module برای نحوه پیاده سازی آن نداریم و کلا DatabaseModule حذف می شود. البته ActivityComponent تغییری نمی کند.</span><br />
</span></p>
<pre class="crayon-plain-tag">public class Database {

    private static final String TAG = "mahditajik.ir";

    @Inject
    User user;
    private Context context;

    @Inject
    public Database(Context context) {
        this.context = context;

    }

    public void initialize() {
        Log.i(TAG, "initialize with context: " + context.toString());

    }

    public void saveToDB() {
        Log.i(TAG, "saveToDB: " + user.toString());
    }
}

@Singleton
@Component(modules = {ApplicationModule.class,UserModule.class})
public interface ApplicationComponent {

    void inject(DaggerTestApplication application);

    // Exported for child-components.

    Context getContext();

    User provideUser();

    //because it had Constructor injected and do not need for Module or exporter
//    Database provideDatabase();

}</pre>
<span style="color: #00ccff;">شاخه lesson2-subcomponent</span> : مثالی است در مورد مطلب مهمی که در اواسط آموزش به آن اشاره کردم:</p>
<h3><span style="color: #99cc00;"><strong>Subcomponent vs Dependency</strong></span></h3>
<p style="text-align: justify;">همانطور که در مثال ملاحظه کردید برای ارتباط <strong>ActivityComponent</strong> با <strong>ApplicationComponent</strong> از <strong>Dependencies</strong> استفاده کردیم</p>
<pre class="crayon-plain-tag">@Component(dependencies = ApplicationComponent.class, modules = ServiceModule.class)</pre>
<p style="text-align: justify;">و سپس هر <strong>Object</strong> که لازم بود را در <strong>ApplicationComponent</strong> برایش یک متد <strong>exporter</strong> نوشتیم. اما راه دیگر استفاده به عنوان <strong>Subcomponent</strong> است. در این روش انترفیس <strong>subcomponent</strong> به همه <strong>Object</strong> های <strong>Component</strong> دسترسی دارد و نیازی به نوشتن متد های <strong>exporter</strong> ندارد و کارایی آن هنگامی است که واقعاً به تمامی <strong>object</strong> ها نیاز داریم. برای شناساندن <strong>Subcomponent</strong> به <strong>Component</strong> اصلی فقط کافیست که یک متد <strong>Factory</strong> برایش در <strong>Component</strong> بنویسیم.</p>
<pre class="crayon-plain-tag">@MahdiScope
@Subcomponent(modules = ServiceModule.class)
public interface ActivityComponent {

    void inject(MainActivity activity);

}

@Singleton
@Component(modules = {ApplicationModule.class, DatabaseModule.class, UserModule.class})
public interface ApplicationComponent {

    void inject(DaggerTestApplication application);


    // Exported for child-components.

//    Context getContext();
//
//    User provideUser();
//
//    Database proDatabase();


    //sub component

    ActivityComponent providesActivityComponent(ServiceModule service);

}</pre>
<p style="text-align: justify;">و برای استفاده wire-up کردن هم متد ماژول ان را از کامپوننت اصلی بگیریم. ( خط ۲۷)</p>
<pre class="crayon-plain-tag">public class MainActivity extends AppCompatActivity {

    @Inject
    NetworkClass networkClass;

    @Inject
    Database database;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initialize();
        webRequest();

    }

    private void webRequest() {

        networkClass.request("https://google.com");
        database.saveToDB();
    }

    private void initialize() {

        ((DaggerTestApplication) getApplicationContext()).getAppComponent()
                .providesActivityComponent(new ServiceModule()).inject(this);

    }
}</pre>
<p style="text-align: justify;">امیدوارم تونسته باشم مطلب رو خوب بیان کنم. در صورت وجود هر گونه مشکل یا سوال یا بحث، که واقعاً این مبحث نیاز به بحث داره، راحت باشید و کامنت بگذارید.</p>
<p><a href="https://github.com/mahdit83/Dagger2SimpleExample" target="_blank" rel="noopener noreferrer"><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2146" src="http://www.mahditajik.ir/wp-content/uploads/2016/12/github_download.png" alt="github_download" width="230" height="70" /></a></p>
<p>بعد از گرفتن پروژه یکبار اون رو import کنید تا قابل اجرا بشه.</p>
<p>منبع: <a href="http://www.biitecode.ir" target="_blank" rel="noopener">بایت کد</a></p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/dagger2-advanced-example/">کار با Dagger2 به زبان ساده  بخش دوم (پیشرفته)</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.mahditajik.ir/dagger2-advanced-example/feed/</wfw:commentRss>
			<slash:comments>14</slash:comments>
		
		
			</item>
		<item>
		<title>برسی Scope@ ها در Dagger2</title>
		<link>http://www.mahditajik.ir/dagger2-custom-scopes/</link>
					<comments>http://www.mahditajik.ir/dagger2-custom-scopes/#comments</comments>
		
		<dc:creator><![CDATA[mahdi]]></dc:creator>
		<pubDate>Mon, 26 Jun 2017 16:18:41 +0000</pubDate>
				<category><![CDATA[آموزش]]></category>
		<category><![CDATA[annotation]]></category>
		<category><![CDATA[Dagger]]></category>
		<guid isPermaLink="false">http://www.mahditajik.ir/?p=2398</guid>

					<description><![CDATA[<p>@Scope annotation اصولا هدف استفاده از این انوتیشن معرفی Scope آبجک تولید شده توسط Dagger2 است. یعنی Dagger2 به شما این امکان را می دهد تا Object های شما چرخه عمر متفاوت داشته باشند و شما فقط تعریف می کنید، پیاده سازی اش با خود Dagger است. فرض کنید که سه component به شرح زیر ...</p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/dagger2-custom-scopes/">برسی Scope@ ها در Dagger2</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></description>
										<content:encoded><![CDATA[<p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2447" src="http://www.mahditajik.ir/wp-content/uploads/2017/07/dagger-scopes.jpg" alt="" width="800" height="486" srcset="http://www.mahditajik.ir/wp-content/uploads/2017/07/dagger-scopes.jpg 800w, http://www.mahditajik.ir/wp-content/uploads/2017/07/dagger-scopes-300x182.jpg 300w, http://www.mahditajik.ir/wp-content/uploads/2017/07/dagger-scopes-768x467.jpg 768w" sizes="(max-width: 800px) 100vw, 800px" /></p>
<p style="text-align: justify;"><span id="crayon-5957802600b1a924909351" class="crayon-syntax crayon-syntax-inline crayon-theme-classic crayon-theme-classic-inline crayon-font-monaco"><span class="crayon-pre crayon-code"><span class="crayon-n">@Scope</span> <span class="crayon-v">annotation</span></span></span></p>
<p style="text-align: justify;">اصولا هدف استفاده از این انوتیشن معرفی Scope آبجک تولید شده توسط <span class="highlight"><a href="http://www.mahditajik.ir/dagger2-advanced-example/" target="_blank" rel="noopener">Dagger2</a> </span>است. یعنی Dagger2 به شما این امکان را می دهد تا Object های شما چرخه عمر متفاوت داشته باشند و شما فقط تعریف می کنید، پیاده سازی اش با خود Dagger است. فرض کنید که سه component به شرح زیر داریم و سلسله مراتب ارتباط و وابستگی Component ها هم مشخص است.</p>
<p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2388" src="http://www.mahditajik.ir/wp-content/uploads/2017/07/dagger-scopes.png" alt="" width="346" height="378" srcset="http://www.mahditajik.ir/wp-content/uploads/2017/07/dagger-scopes.png 346w, http://www.mahditajik.ir/wp-content/uploads/2017/07/dagger-scopes-275x300.png 275w" sizes="(max-width: 346px) 100vw, 346px" /></p>
<p>و ما برای آنها سه اسکوپ تعریف می کنیم. <strong>ActivityScope</strong>, <strong>UserScope</strong>, <strong>Applicationscope(singletone)</strong>.</p>
<p style="text-align: justify;"><strong>Dagger2</strong> به طور پیش فرض <strong>singletone</strong> یا همان <strong>applicationScope</strong> را دارد و چرخه عمرآن با چرخه عمر <strong>Application</strong> یکی است. احتمالاً در کد <strong>autogenerated</strong> خودش بصورت <strong>static</strong> نگهداری می کند. استفاده از این اسکوپ ها مانند این است که <strong>tag</strong> تعریف کنیم و اسمشان اهمیتی ندارد. فقط <strong>Object</strong> ای که با اسکوپ خاصی تولید می شود، طول عمر و <strong>LifeCycle</strong> اش با صدا زننده آن یکی خواهد شد. مثلا اگر یک <strong>Object</strong> با <strong>ActivityScope@</strong> داریم که در درون <strong>activity</strong> تزریق می شود، <strong>Lifecycle </strong> آن با <strong>Lifecycle</strong> مربوط به <strong>activity</strong> یکی می شود و تا زمانی وجود دارد که <strong>Activty</strong> تزریق کننده آن وجود داشته باشد و کنترل کردن آن اتوماتیک توسط <strong>Dagger2</strong> انجام می شود.</p>
<p style="text-align: justify;">به تصویر زیر توجه کنید:<img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2389" src="http://www.mahditajik.ir/wp-content/uploads/2017/07/scopes-lifecycle.png" alt="" width="2226" height="1080" srcset="http://www.mahditajik.ir/wp-content/uploads/2017/07/scopes-lifecycle.png 2226w, http://www.mahditajik.ir/wp-content/uploads/2017/07/scopes-lifecycle-300x146.png 300w, http://www.mahditajik.ir/wp-content/uploads/2017/07/scopes-lifecycle-768x373.png 768w, http://www.mahditajik.ir/wp-content/uploads/2017/07/scopes-lifecycle-1024x497.png 1024w" sizes="(max-width: 2226px) 100vw, 2226px" /></p>
<p style="text-align: justify;"><strong>ApplicationScope</strong> در طول کل برنامه وجود دارد. پس ما برای هر آیتمی این اسکوپ را بگذاریم تا پایان برنامه وجود خواهد داشت. با شروع هر اکتیویتی، <strong>ActivityScope</strong> شروع و با بسته شدن آن اسکوپ هم تمام می شود. همچنین برای <strong>UserScope</strong>. با انتخاب یا ساخت هر یوزری شروع و  در نهایت با رهاکردن آن، تمام می شود.</p>
<p style="text-align: justify;">پس یادمان باشد که نام <strong>Scope</strong> ها مهم نیست. بلکه این مهم است که برای چه <strong>Provider</strong> ای تعریف شده و آن <strong>Object</strong> در چه کلاسی <strong>Inject</strong> می شود. برای ساخت آن بدین صورت عمل می کنیم:</p>
<pre class="crayon-plain-tag">@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ScopeName{
}</pre>
منبع: <a href="http://www.biitecode.ir" target="_blank" rel="noopener">بایت کد</a></p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/dagger2-custom-scopes/">برسی Scope@ ها در Dagger2</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.mahditajik.ir/dagger2-custom-scopes/feed/</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
			</item>
		<item>
		<title>کار با Dagger2 به زبان ساده  بخش اول</title>
		<link>http://www.mahditajik.ir/dagger2-simple-example/</link>
					<comments>http://www.mahditajik.ir/dagger2-simple-example/#comments</comments>
		
		<dc:creator><![CDATA[mahdi]]></dc:creator>
		<pubDate>Tue, 06 Dec 2016 14:58:27 +0000</pubDate>
				<category><![CDATA[آموزش]]></category>
		<category><![CDATA[Dagger]]></category>
		<category><![CDATA[dagger چیست]]></category>
		<category><![CDATA[Dependency]]></category>
		<category><![CDATA[Dependency Injection]]></category>
		<category><![CDATA[DI]]></category>
		<category><![CDATA[Injection]]></category>
		<category><![CDATA[learning]]></category>
		<category><![CDATA[تزریق]]></category>
		<category><![CDATA[وابستگی]]></category>
		<guid isPermaLink="false">http://www.mahditajik.ir/?p=2117</guid>

					<description><![CDATA[<p>چقدر خوب می شد اگر هر وقت نیازمندی داشتیم فقط آن را مطرح می کردیم و به سادگی برایمان فراهم می شد؟ مفهوم Dependency Injection یا به اختصار DI همین است، شما فقط می گویید من آن object را می خواهم و شخص دیگری آن را با تمام پیچیدگی هایش برایتان فراهم می کند! در ...</p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/dagger2-simple-example/">کار با Dagger2 به زبان ساده  بخش اول</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></description>
										<content:encoded><![CDATA[<p style="text-align: justify;"><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2169" src="http://www.mahditajik.ir/wp-content/uploads/2016/12/mahditajik_ir_learning-tempelate2-1-1.jpg" alt="" width="800" height="486" srcset="http://www.mahditajik.ir/wp-content/uploads/2016/12/mahditajik_ir_learning-tempelate2-1-1.jpg 800w, http://www.mahditajik.ir/wp-content/uploads/2016/12/mahditajik_ir_learning-tempelate2-1-1-300x182.jpg 300w, http://www.mahditajik.ir/wp-content/uploads/2016/12/mahditajik_ir_learning-tempelate2-1-1-768x467.jpg 768w" sizes="(max-width: 800px) 100vw, 800px" /></p>
<p style="text-align: justify;">چقدر خوب می شد اگر هر وقت نیازمندی داشتیم فقط آن را مطرح می کردیم و به سادگی برایمان فراهم می شد؟ مفهوم <strong>Dependency Injection</strong> یا به اختصار <strong>DI</strong> همین است، شما فقط می گویید من آن <strong>object</strong> را می خواهم و شخص دیگری آن را با تمام پیچیدگی هایش برایتان فراهم می کند! در ضمن تمام امور مربوط به تولید، نگهداری، چرخه حیات و مسائل مربوط آن شئی را برایمان کنترل می کند و باعث می شود ارتباطات بین کلاس ها ساده تر شود و در نتیجه نگهداری و توسعه ساده تر گردد. قرار است این کار را توسط <strong>Dagger2</strong> در اندروید پیاده سازی نماییم.</p>
<p><strong><span style="color: #99cc00;">مقدمه:</span></strong></p>
<blockquote><p>Dependency Injection is a set of software design principles and patterns that enable us to develop loosely coupled code.</p>
<p>Loose coupling makes code extensible, and extensibility makes it maintainable</p>
<p>Mark Seemann</p></blockquote>
<p style="text-align: justify;">یکی از اصول <strong>SOLID</strong> اصل <strong>Dependency Inversion Principle</strong> است که یکی از دیزاین پترن هایی که آن را پیاده سازی می کند <strong>Dependency Injection</strong> است که هدف اصلی آن کم کردن وابستگی ها برای نگهداری و توسعه راحت تر می باشد. در صورتی که علاقه مند به آشنایی بیشتر با این دیزان پترن هستید  می توانید کتاب <strong>Mark seemann</strong> را از اینجا <a href="http://www.mahditajik.ir/download_contents/Manning.Dependency.Injection.In.Dot.NET.Sep.2011.ISBN.1935182501.pdf" target="_blank" rel="noopener noreferrer"><span style="text-decoration: underline;">دانلود</span></a> کنید. در ضمن دوست و همکار عزیزم مثالی خوب و  ملموسی با نام <a href="http://www.digigene.com/design-patterns/dependency-injection-coffeeshop/" target="_blank" rel="noopener noreferrer">&#8220;Dependency Injection in the Coffeeshop&#8221;</a> دارد که دیدن آن خالی از لطف نیست. Dagger</p>
<p style="text-align: justify;">  <strong>Dagger2</strong> یک <strong>Dependency Injection FrameWork</strong> است که <strong>Dependency Injection</strong> را با استفاده از تولید خودکار کد بر پایه <a href="http://www.mahditajik.ir/java-annotation-%da%86%db%8c%d8%b3%d8%aa%d8%9f/" target="_blank" rel="noopener noreferrer">annotations </a>بهره می گیرد (در مورد انوتیشن می توانید به <span style="text-decoration: underline;"><a href="http://www.mahditajik.ir/java-annotation-%da%86%db%8c%d8%b3%d8%aa%d8%9f/" target="_blank" rel="noopener noreferrer">این آموزش</a></span> مراجعه کنید) یعنی برای استفاده از امکانات آن باید از <strong>annotation</strong> های خاصی استفاده کنیم که به توضیح آنها خواهم پرداخت. بخاطر اینکه  کار با <strong>Dagger2</strong> کمی ابهام دارد و فهم آن برای خودم هم کمی طول کشید، مثال ساده ای آماده کردم که نحوه کار با <strong>Dagger2</strong> را خیلی واضح و راحت باهم برسی کنیم. فقط توجه داشته باشید که هدف اصلی این مقاله نحوه کارکرد با <strong>Dagger2</strong> است و نه پیاده سازی صددرصد صحیح <strong>Dependency Injection</strong> و تلاش می کنیم در مقاله دوم به این امر نیز پرداخته و پروژه را از هر نظر باهم تکمیل کنیم.</p>
<p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2808" src="http://www.mahditajik.ir/wp-content/uploads/2016/12/principles-and-patterns.jpg" alt="" width="602" height="241" srcset="http://www.mahditajik.ir/wp-content/uploads/2016/12/principles-and-patterns.jpg 602w, http://www.mahditajik.ir/wp-content/uploads/2016/12/principles-and-patterns-300x120.jpg 300w" sizes="(max-width: 602px) 100vw, 602px" /></p>
<p style="text-align: justify;">به نظرم یک از دلایل پیچیدگی های کار با <strong>Dagger2</strong> ، روش های گوناگون پیاده سازی آن است که شاید بعضاً کار کند ولی از نظر DI درست نباشد و می توان با اطلاع  از این روش ها تسلط خوبی برآن پیدا کرد. بنابر این سعی می کنم به مرور کد را تمیز تر و به DI اصولی نزدیک تر کنم. پس تا آخر این مقاله با من باشید و درصورت وجود هرگونه ابهام یا ایراد یا سوال آن را با من در میان بگذارید تا در اسرع وقت پاسخ دهم.</p>
<p style="text-align: justify;"><span style="color: #99cc00;"><strong>قدم اول: اضافه کردن Dagger2 به پروژه</strong></span></p>
<p>اول از همه اطلاعات زیر را به <strong>Gradle</strong> سطح پروژه اضافه کنید:</p><pre class="crayon-plain-tag">dependencies {
    
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}</pre><p>
سپس خط زیر را در آخر <strong>Gradle</strong> سطح برنامه اضافه کنید.</p><pre class="crayon-plain-tag">apply plugin: 'com.neenbedankt.android-apt'</pre><p>
و وابستگی های زیر را نیز به همان فایل اضافه نمایید</p><pre class="crayon-plain-tag">dependencies {
    compile 'com.google.dagger:dagger:2.7'
    apt 'com.google.dagger:dagger-compiler:2.7'
    provided 'javax.annotation:jsr250-api:1.0'
}</pre><p>
سپس <strong>Gradle</strong> خود را <strong>sync</strong> کنید.</p>
<p><span style="color: #333333;"><strong>به روز رسانی:</strong> </span>اخیراً به علت کاربرد زیاد <strong>Dagger</strong> گوگل امکان اضافه کردن این کتابخانه را بصورت مستقیم فراهم کرده و می توان بدین صورت نیز عمل کرد:</p><pre class="crayon-plain-tag">compile 'com.google.dagger:dagger:2.7'
annotationProcessor 'com.google.dagger:dagger-compiler:2.7'</pre><p>
&nbsp;</p>
<p><span style="color: #99cc00;"><strong>قدم دوم: آماده سازی کلاس هایی که می خواهیم برایمان تزریق شوند و ارتباط بین آنها (Wiring up)</strong></span></p>
<p style="text-align: justify;">مفاهیم اصلی مطرح در <strong>Dagger2</strong> به شرح زیر می باشند که همانطور که اشاره کردم برای استفاده از این مفاهیم باید از انوتیشن های هم نام آنها استفاده کرد.</p>
<pre class="crayon-plain-tag">Provides@</pre>
<p style="text-align: justify;">نحوه تولید وابستگی ها را مشخص می کند. هر جا که این انوتیشن بروی متدی بود یعنی خروجی این متد قرار است در جایی از برنامه تزریق شده و مورد استفاده قرار گیرد.</p>
<pre class="crayon-plain-tag">Module@</pre>
<p style="text-align: justify;">کلاسی هست که <strong>Provider</strong> ها در آن قرار می گیرند.</p>
<pre class="crayon-plain-tag">Component@</pre>
<p style="text-align: justify;">اینترفیسی که ارتباط وابستگی ها و استفاده کننده آن را مطرح می کند. ما فقط اینترفیس را می نویسیم و پیاده سازی آن با خود <strong>Dagger</strong> است.</p>
<pre class="crayon-plain-tag">Inject@</pre>
<p style="text-align: justify;">هرکجا که نیاز به تزریق وابستگی داشتیم از این انوتیشن استفاده می کنیم.</p>
<p style="text-align: justify;">قصد ندارم که مانند خیلی از مقاله ها سرتان رو با تعاریف اولیه درد بیارم، پس صاف می رویم سر مثال که کاربرد این انوتیشن ها را ببینیم.</p>
<p style="text-align: justify;"><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2171" src="http://www.mahditajik.ir/wp-content/uploads/2016/12/photo_2016-12-07_20-46-00.jpg" alt="" width="1280" height="800" srcset="http://www.mahditajik.ir/wp-content/uploads/2016/12/photo_2016-12-07_20-46-00.jpg 1280w, http://www.mahditajik.ir/wp-content/uploads/2016/12/photo_2016-12-07_20-46-00-300x188.jpg 300w, http://www.mahditajik.ir/wp-content/uploads/2016/12/photo_2016-12-07_20-46-00-768x480.jpg 768w, http://www.mahditajik.ir/wp-content/uploads/2016/12/photo_2016-12-07_20-46-00-1024x640.jpg 1024w" sizes="(max-width: 1280px) 100vw, 1280px" /></p>
<p style="text-align: justify;">برنامه ای داریم که قرار است موتور خودرو تولید کند و جهت تست، آن را روشن کرده و استارت بزند.  موتور ماشین وابسته به کامپیوتر داخلی و رادیاتور می باشد. ( این بخش ها را می توان بیشتر کرد ولی جهت سادگی فرض کنید موتور فقط نیازمند این دوبخش است.) و می خواهیم به کمک <strong>Dagger2</strong> هرجا نیازی به کلاس خودرو شد بدون اینکه درگیر وابستگی های آن یعنی  کامپوتر و رادیاتور شویم، فقط بگوییم یک موتور آماده تحویل ما بده. کلاس ها رو بصورت زیر تعریف می کنیم:</p>
<pre class="crayon-plain-tag">public class Computer {

    private int voltage;
    private String model;

    public Computer(String model ,int voltage){

        this.model=model;
        this.voltage = voltage;
    }
}</pre>
<pre class="crayon-plain-tag">public class Radiator {
    private String name;

    public Radiator(String name){
        this.name = name;
    }
}</pre>
<p style="text-align: justify;">همانطور که دیدیم دو کلاس رادیاتور و کامپیوتر را داریم که وابستگی خاصی ندارند. حال نوبت به تعریف کلاس موتور می رسد. برای ایجاد و بیان وابستگی از انوتیشن <strong>Inject@ </strong>استفاده می کنیم و <strong>Dagger</strong> می فهمد که باید یک وابستگی را تزریق کند.</p>
<pre class="crayon-plain-tag">public class Motor {

    @Inject
    public Computer computer;

    @Inject
    Radiator radiator;

    String name;

    public Motor(String name) {
        this.name = name;
    }

    public boolean startEngin() {
        if (computer != null &amp;&amp; radiator != null) {
            return true;
        } else {
            return false;
        }
    }

    public Computer getComputer() {
        return computer;
    }


    public String getName() {
        return name;
    }

    public Radiator getRadiator(){
        return radiator;
    }
}</pre>
<p style="text-align: justify;">پس ما تا اینجا نحوه وابستگی کلاس ها را با انوتیشن <strong>Inject@ </strong>مشخص کردیم. یعنی به <strong>Dagger</strong> گفتیم که هنگام ساخت موتور رادیاتور و کامپیوتر را در اختیارم قرار بده! ( حالا نمی دانم چطوری، هرطور خودت صلاح می دونی!) ولی قبل آن لازم است تا یکبار نحوه ساخته شدن وابستگی ها را به <strong>Dagger</strong> را معرفی کنیم. برای اینکار کلاسی با نام ماژول می سازیم که از انوتیشن <strong>Module@ </strong>استفاده می کند و بخش های آن که نحوه ساختن وابستگی را شرح می دهند با انوتیشن <strong>Provides@ </strong>مشخص می کنیم.</p>
<pre class="crayon-plain-tag">@Module
public class MotorModule {

    String motoName;
    String computerName;
    String radiatorName;
    int voltage;

    public MotorModule(String computerName, int voltage , String radiatorName) {
        this.radiatorName = radiatorName;
        this.computerName = computerName;
        this.voltage = voltage;
    }


    @Provides
    @Singleton
    Motor provideMotor() {
        return new Motor(motoName);
    }

 

    @Provides
    @Singleton
    Computer provideComputer() {
        return new Computer(computerName, voltage);
    }


    @Provides
    @Singleton
    Radiator provideRadiator(){
        return new Radiator(radiatorName);
    }
}</pre>
<p style="text-align: justify;">اگر قرار است وابستگی های ما ورودی داشته باشند آن را در <strong>Constructor</strong> مربوط به <strong>Module</strong> پاس می دهیم. همانطور که می بینید اسم رادیاتور، اسم کامپیوتر و ولتاژ آن ( که جزو ورودی های ما بودند) به همراه <strong>Constructor</strong> پاس داده شد. ما در <strong>Module</strong> به <strong>Dagger</strong> می فهمانیم که وقتی آبجکتی خواستیم آن را چگونه تولید کند. در ضمن با استفاده  ازاسکوپ <strong>Singletone@ </strong>به <strong>Dagger</strong> می فهمانیم که همیشه یک نمونه از آن داشته باشد و هر دفعه یک نمونه جدید تولید نکند. برای مشاهده نحوه کار <strong>Scope</strong> به <span class="highlight"><a href="http://www.mahditajik.ir/dagger2-custom-scopes/" target="_blank" rel="noopener">این مقاله</a></span> مراجعه کنید.</p>
<p style="text-align: justify;">کلاسی بعدی که به آن نیاز داریم <strong>interface</strong> ای هست که <strong>Dagger</strong> توسط آن می فهمد که کدام ماژول ها را در کجا باید تزریق کند و برای تولید کد خودکار <strong>Dagger</strong> مورد نیاز است، ولی اجازه بدهید تا این کلاس را بعد از نحوه استفاده از <strong>Dagger</strong> شرح دهم. فقط همین اندازه بدانیم که دو متد با نام دلخواه ( من نام هردو را <strong>void inject </strong>گذاشتم.) یکی با ورودی <strong>MainActivity </strong>و دیگری <strong>Motor </strong>ساختم.</p>
<pre class="crayon-plain-tag">@Singleton
@Component(modules = {MotorModule.class})
public interface MotorComponent {

    void inject(MainActivity activty);
    void inject(Motor moto);

}</pre>
<p style="text-align: justify;">خیلی خوب. حال همه چیز آماده است و نوبت به این می رسد که  <strong>object</strong> مورد نظرمان یعنی موتور را در کلاس تزریق و استفاده کنیم. فقط یک نکته باقی مانده است. لازم است تا <strong>Dagger</strong> کد خودکار را تولید کند و ورودی ماژول را به آن بدهیم تا کل ارتباطات کامل و تمامی آبجکت ها قابل تزریق باشد. اصطلاحاً سیم کشی یا <strong>Wiring up</strong> را تمام کنیم.  فقط توجه نمایید که برای اینکه dagger بتواند کدهای مربوطه خود را auto generate کند بعد از این بخش ( یعنی ساخت ماژول ها و کامپوننت) باید کل پروژه را <strong>Rebuild</strong> کنیم. به متد <strong>generateDaggerCode </strong>توجه نمایید:</p>
<pre class="crayon-plain-tag">public class MainActivity extends AppCompatActivity {

    @Inject
    public Motor motor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        generateDaggerCode();

        createCar(motor);

    }

    private void createCar(Motor motor) {

        if (motor != null) {
            Toast.makeText(this, "car is created", Toast.LENGTH_SHORT).show();
        }

        startCar(motor);
    }

    private void startCar(Motor motor) {
        if (motor.startEngin()) {

            Toast.makeText(this, "it is started", Toast.LENGTH_SHORT).show();
            Toast.makeText(this, "motor name is:" + motor.getName(), Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "motor is not provided", Toast.LENGTH_SHORT).show();
        }
    }

    private void generateDaggerCode() {
        MotorComponent component = DaggerMotorComponent.builder().motorModule(new MotorModule
                (this, "Computer name",12, "radiator name")).build();

    component.inject(this);
    component.inject(motor);
      
    }
    
}</pre>
<p style="text-align: justify;"><span style="color: #99cc00;"><strong>حال به تجزیه تحلیل کد دقت نمایید</strong></span></p>
<p style="text-align: justify;">اول از همه کد <strong>Dagger</strong> را تولید می کنیم که در ورودی آن ماژول را با ورودی آن پاس می دهیم. ( نام رادیاتور، نام کامپیوتر، ولتاژ) سپس دو متد موجود در <strong>Component</strong> را صدا می زنیم. حال ما هرجای این کد که یک موتور خواستیم کافی است آن را با <strong>Inject@ </strong>بیاوریم و خود <strong>Dagger</strong> آن را مدیریت می کند.</p>
<p style="text-align: justify;">چند نکته و قانون وجود دارد که فهم آنها باعث می شود این پیچیدگی کم شود. اول اینکه اگر هرجایی <strong>Inject</strong> را در فیلد های یک کلاس انجام دادیم ( مثل همین جا که در <strong>MainActivity </strong>کلاس <strong>Motor </strong>را در اول کلاس تزریق کرده و سپس از آن استفاده کردیم) <strong>Dagger</strong> متوجه آن نمی شود مگر اینکه  یک متدی ( با نام دلخواه) در <strong>Component</strong> بنویسم که ورودی آن، همان کلاس استفاده کننده باشد تا <strong>Dagger</strong> بفهمد چه کلاسی در فیلد خود <strong>Inject</strong> انجام داده و بتواند کد خود را بصورت صحیح تولید کند. برای همین امر بود که در <strong>Component</strong> یک متد به نام <strong>inject</strong> ساختم که ورودی آن <strong>MainActivity </strong>بود. همانطور که ملاحظه می کنید چون خود <strong>Motor </strong>هم در داخل خودش <strong>field Injection</strong> داشت ( هم <strong>Computer</strong> و هم <strong>Radiator</strong> در خط ۴ و ۷ کلاس موتور) پس ناچاراً متدی هم برای آن در <strong>Component</strong> نوشتم تا ارتباط آنها را نیز متوجه بشود و به اصطلاح فیلداینجکشن ها را اسکن کند.</p>
<p style="text-align: justify;">اگر برنامه را اجرا کنید <strong>Motor</strong> به درستی <strong>Inject</strong> شده و پیغام مناسب دریافت خواهید کرد و ما توانسته ایم با استفاده از <strong>Dagger2</strong> وابستگی را به کد تزریق کنیم.</p>
<p style="text-align: justify;">حال توجه شما را به یک پیاده سازی دیگر جلب می نمایم. در این روش برای ساخت موتور، اجزای لازم را بدون استفاده از انوتیشن <strong>Inject@ </strong>و با <strong>Constructor</strong> پاس می دهم. همانطور که در بالا گفتیم چون تزریق در فیلد انجام ندادیم پس در کامپوننت هم متد آن ( <span style="color: #0000ff;">void inject(Motor moto)</span>) را حذف می کنیم. بدین صورت:</p>
<pre class="crayon-plain-tag">public class Motor {

    private Computer computer;
    private Radiator radiator;
    private String name;

    public Motor(String name, Computer computer ,Radiator radiator) {
        this.name = name;
        this.computer = computer;
        this.radiator = radiator;
    }

    public boolean startEngin() {
        if (computer != null &amp;&amp; radiator != null) {
            return true;
        } else {
            return false;
        }
    }

    public Computer getComputer() {
        return computer;
    }


    public String getName() {
        return name;
    }

    public Radiator getRadiator() {
        return radiator;
    }
}</pre>
<p style="text-align: justify;">پس <strong>Dagger</strong> می فهمد که برای ساخت موتور باید دو ورودی رادیاتور و کامپیوتر به موتور پاس دهد، از طرفی نحوه ساخت کامپیوتر و رادیاتور را می داند. پس همین کافی است که بتواند موتور را برایمان تولید کند و <strong>Component</strong> هم بصورت زیر می شود:</p>
<pre class="crayon-plain-tag">@Singleton
@Component(modules = {MotorModule.class})
public interface MotorComponent {

    void inject(MainActivity activty);

}</pre>
<p style="text-align: justify;">حال اگر از شما بپرسند چرا متدی قرار دادیم با نام <strong>inject</strong> که ورودی آن از جنس <strong>MainActivity</strong> است جواب دهید: بخاطر اینکه در <strong>MainActivity </strong>در فیلد <strong>Motor </strong>را تزریق کرده ایم! بله درست گفتید!</p>
<pre class="crayon-plain-tag">public class MainActivity extends AppCompatActivity {

    @Inject
    public Motor motor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        generateDaggerCode();

        createCar(motor);

    }

    private void createCar(Motor motor) {

        if (motor != null) {
            Toast.makeText(this, "car is created", Toast.LENGTH_SHORT).show();
        }

        startCar(motor);
    }

    private void startCar(Motor motor) {
        if (motor.startEngin()) {

            Toast.makeText(this, "it is started", Toast.LENGTH_SHORT).show();
            Toast.makeText(this, "motor name is:" + motor.getName(), Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "motor is not provided", Toast.LENGTH_SHORT).show();
        }
    }

    private void generateDaggerCode() {
        DaggerMotorComponent.builder().motorModule(new MotorModule
                (this, "Computer name",12, "radiator name")).build().inject(this);


    }

}</pre>
<p style="text-align: justify;">همانطور که ملاحظه کردید هرجایی که بخواهیم وابستگی را تزریق کنیم باید  از <strong>Inject@ </strong>استفاده کنیم و بنابراین باید کلاسی که در آن تزریق کرده ایم را توسط متدی در <strong>Component</strong> به <strong>Dagger</strong> معرفی کنیم. به نظر می رسد که بهتر است در هنگام ایجاد و تعریف وابستگی ها (<strong>Register</strong>) تا حد امکان از <strong>Inject@ </strong>استفاده نکنیم و در صورت امکان بصورت ورودی به <strong>Constructor</strong> بدهیم. دلیل من هم این است که هم خوانایی کد بالا می رود و هم تعداد متدهای <strong>Component</strong> کمتر می شود و در هنگام <strong>Resolve</strong> از <strong>Inject@ </strong>استفاده کنیم. ( <strong>Register</strong>, <strong>Resolve</strong>, <strong>Release</strong> پترنی است که در <a href="http://blog.ploeh.dk/2010/09/29/TheRegisterResolveReleasepattern/" target="_blank" rel="noopener noreferrer">DI Container</a> مورد استفاده قرار می گیرد که در مقاله بعد بیشتر راجع به آن صحبت خواهم کرد. )</p>
<p style="text-align: justify;">بسیار عالی. تا اینجا با نحوه استفاده از <strong>Dagger2</strong> آشنا شدید و دو نمونه از پیاده سازی های آن را دیدید. <strong>Dagger2</strong> امکانات بسیار زیاد دیگری نیز دارد که انشاء الله در آموزش بعدی به همراه برسی چند مورد نکته دیگر، به آنها پرداخته و پرونده را به کل می بندیم. در ضمن می توانید پروژه تست را از گیت دانلود کنید:</p>
<p style="text-align: justify;"><a href="https://github.com/mahdit83/Dagger2SimpleExample" target="_blank" rel="noopener noreferrer"><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2146" src="http://www.mahditajik.ir/wp-content/uploads/2016/12/github_download.png" alt="github_download" width="230" height="70" /></a>منبع: <a href="http://www.biitecode.ir" target="_blank" rel="noopener">بایت کد</a></p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/dagger2-simple-example/">کار با Dagger2 به زبان ساده  بخش اول</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.mahditajik.ir/dagger2-simple-example/feed/</wfw:commentRss>
			<slash:comments>27</slash:comments>
		
		
			</item>
	</channel>
</rss>
