<?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>learning &#8211; Mahdi Tajik</title>
	<atom:link href="http://www.mahditajik.ir/tag/learning/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>learning &#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-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>
		<item>
		<title>Memrise Learn Languages Premium</title>
		<link>http://www.mahditajik.ir/memrise-learn-languages/</link>
					<comments>http://www.mahditajik.ir/memrise-learn-languages/#respond</comments>
		
		<dc:creator><![CDATA[mahdi]]></dc:creator>
		<pubDate>Wed, 06 Jul 2016 07:23:04 +0000</pubDate>
				<category><![CDATA[معرفی]]></category>
		<category><![CDATA[app]]></category>
		<category><![CDATA[language]]></category>
		<category><![CDATA[learning]]></category>
		<category><![CDATA[آموزش زبان]]></category>
		<guid isPermaLink="false">http://www.mahditajik.ir/?p=1993</guid>

					<description><![CDATA[<p>نرم افزار پیشنهادی این ماه من نرم افزار اندروید آموزش زبان انگلیسی Memrise Learn Languages Premium که به زبان آموزان در امر یادگیری زبان انگلیسی و سایر زبان ها کمک شایانی می کند. قصد دارید زبان جدیدی یاد بگیرید ولی زمان کافی ندارید؟ یا ممکن است بخواهید دایره‌ی وازگان زبانی تان را گسترش دهید. این ...</p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/memrise-learn-languages/">Memrise Learn Languages Premium</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-1996" src="http://www.mahditajik.ir/wp-content/uploads/2016/07/com.memrise.android.memrisecompanion-1.png" alt="com.memrise.android.memrisecompanion" width="512" height="512" srcset="http://www.mahditajik.ir/wp-content/uploads/2016/07/com.memrise.android.memrisecompanion-1.png 512w, http://www.mahditajik.ir/wp-content/uploads/2016/07/com.memrise.android.memrisecompanion-1-150x150.png 150w, http://www.mahditajik.ir/wp-content/uploads/2016/07/com.memrise.android.memrisecompanion-1-300x300.png 300w, http://www.mahditajik.ir/wp-content/uploads/2016/07/com.memrise.android.memrisecompanion-1-70x70.png 70w" sizes="(max-width: 512px) 100vw, 512px" /><br />
نرم افزار پیشنهادی این ماه من نرم افزار اندروید آموزش زبان انگلیسی Memrise Learn Languages Premium که به زبان آموزان در امر یادگیری زبان انگلیسی و سایر زبان ها کمک شایانی می کند. قصد دارید زبان جدیدی یاد بگیرید ولی زمان کافی ندارید؟ یا ممکن است بخواهید دایره‌ی وازگان زبانی تان را گسترش دهید. این نرم افزار به شما کمک می کند چیزهای جدید را آسان و سرگرم کننده در ذهن خود جای دهید.</p>
<p style="text-align: justify;">در این برنامه بیش از ۲۰۰ زبان از جمله فارسی، اسپانیایی، فرانسوی، آلمانی، پرتغالی (برزیل پرتغالی و پرتغالی اروپا)، چینی ماندارین (حروف چینی سنتی و ساده شده)، کانتونی، ژاپنی، کره ای، ایتالیایی، ایرلندی، ولزی، هلندی، دانمارکی، سوئدی، فنلاندی، کاتالان، ایسلندی، لهستانی، روسی، عربی (استاندارد عربی، مراکش عربی، مصر عربی، خلیج عربی و غیره) … و حتی زبان های ساخته شده از اسپرانتو به کلینگون، توکی پونا، دوتراکی و Na’Vi برای یادگیری، تمرین های SAT, GMAT, TESOL, TOEFL و دوره های GCSE, A-Level, IBAC وجود دارد. در این اپلیکیشن جوامع آموزشی از کاربران وجود دارند که می توانید آموزش ها را از این جامعه ها دریافت کنید یا آموزش های خود را در آن به اشتراک بگذارید. این برنامه به صورت رایگان و آنلاین می باشد.</p>
<p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-1999" src="http://www.mahditajik.ir/wp-content/uploads/2016/07/com.memrise.android.memrisecompanion8.png" alt="com.memrise.android.memrisecompanion8" width="650" height="900" srcset="http://www.mahditajik.ir/wp-content/uploads/2016/07/com.memrise.android.memrisecompanion8.png 650w, http://www.mahditajik.ir/wp-content/uploads/2016/07/com.memrise.android.memrisecompanion8-217x300.png 217w" sizes="(max-width: 650px) 100vw, 650px" /></p>
<p>&nbsp;</p>
<p>برخی از ویژگی های برنامه Memrise Learn Languages Premium اندروید :<br />
✤ سیستم آموزش علمی افزایش مغز شما برای یادگیری ۴۴ کلمه در ساعت<br />
✤ حالت های بازی چندگانه تمرین جنبه های مختلف حافظه: یادگیری بصری، بررسی و غیره</p>
<p style="text-align: center;"><a href=" https://cafebazaar.ir/app/com.memrise.android.memrisecompanion/?l=fa/?l=fa" target="_blank" class="shortc-button medium green">دانلود نرم افزار</a>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/memrise-learn-languages/">Memrise Learn Languages Premium</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.mahditajik.ir/memrise-learn-languages/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>کار با Account-manager اندروید</title>
		<link>http://www.mahditajik.ir/account-manager/</link>
					<comments>http://www.mahditajik.ir/account-manager/#comments</comments>
		
		<dc:creator><![CDATA[mahdi]]></dc:creator>
		<pubDate>Mon, 23 May 2016 07:56:52 +0000</pubDate>
				<category><![CDATA[آموزش]]></category>
		<category><![CDATA[accountmanager]]></category>
		<category><![CDATA[learning]]></category>
		<category><![CDATA[اندروید]]></category>
		<category><![CDATA[حساب کاربری]]></category>
		<guid isPermaLink="false">http://www.mahditajik.ir/?p=1821</guid>

					<description><![CDATA[<p>مطلبی که این جلسه قصد آموزش آن را دارم کار با سیستم مدیریت حساب داخلی اندروید می باشد. می خواهیم در یک پروژه عملی یک حساب کاربری دلخواه بسازیم و بعد از ثبت نام اولیه , تایید از سرور، برنامه با استفاده از حساب کاربری داخلی ایجاد شده بطور خودکار لاگین کند. با توجه به اینکه ...</p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/account-manager/">کار با Account-manager اندروید</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-1845" src="http://www.mahditajik.ir/wp-content/uploads/2016/05/learning-tempelate.jpg" alt="learning-tempelate" width="800" height="486" srcset="http://www.mahditajik.ir/wp-content/uploads/2016/05/learning-tempelate.jpg 800w, http://www.mahditajik.ir/wp-content/uploads/2016/05/learning-tempelate-300x182.jpg 300w, http://www.mahditajik.ir/wp-content/uploads/2016/05/learning-tempelate-768x467.jpg 768w" sizes="(max-width: 800px) 100vw, 800px" /></p>
<p style="text-align: justify;">مطلبی که این جلسه قصد آموزش آن را دارم کار با سیستم مدیریت حساب داخلی اندروید می باشد. می خواهیم در یک پروژه عملی یک حساب کاربری دلخواه بسازیم و بعد از ثبت نام اولیه , تایید از سرور، برنامه با استفاده از حساب کاربری داخلی ایجاد شده بطور خودکار لاگین کند. با توجه به اینکه منابع زیادی در این رابطه حتی به انگلیسی موجود نمی باشد، امیدوارم این مطلب برایتان مفید واقع شود. در واقع مشکل از جایی شروع شد که خودم به دنبال پیداکردن جوابی برای آن بودم نهایتاً تجربه شخصی خودم را برایتان به اشتراک می گذارم. البته در آموزش امروز با اصول اولیه حساب کاربری آشنا خواهیم شد و اصل مطلب برای آموزش بعدیست!</p>
<blockquote><p>This class provides access to a centralized registry of the user&#8217;s online accounts. The user enters credentials (username and password) once per account, granting applications access to online resources with &#8220;one-click&#8221; approval.</p></blockquote>
<p>طبق تعریف رسمی اندروید: AccountManager کلاسی است که ثبت نام های آنلاین کاربر را متمرکز کرده و با توجه به اطلاعاتی که از کاربر نگهداری می کند( از قبیل نام کاربری و کلمه عبور)، ارتباط با آن (کاربر ثبت شده) و استفاده از منابع آن را توسط برنامه ها به آسانی فراهم می کند.</p>
<p>برای کار با AccountManager اندروید نیاز به سه آیتم اصلی داریم که هرکدام را ملاحظه خواهید کرد.</p>
<ul>
<li>سرویس ویژه مدیریت حساب</li>
<li>فایل xml حاوی اطلاعات مربوط به حساب کاربری</li>
<li>یک نمونه از کلاس AbstractَAccountAuthenticator</li>
</ul>
<pre class="crayon-plain-tag">public class MyAthenticator extends AbstractAccountAuthenticator {
    
    public MyAthenticator(Context context) {
        super(context);
    }

    @Override
    public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
        return null;
    }

    @Override
    public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {

        Log.i("MAHDI","on add account");
        return null;
    }

    @Override
    public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
        return null;
    }

    @Override
    public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
        return null;
    }

    @Override
    public String getAuthTokenLabel(String authTokenType) {
        return null;
    }

    @Override
    public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
        return null;
    }

    @Override
    public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
        return null;
    }
}</pre>
<p style="text-align: justify;">در این کلاس مشتق شده متدها بطور خودکار تولید می شوند و توضیح اینکه کار اصلی آن چه است برای آموزش بعدی و فقط این را بدانید که اجباری است. من  فقط در متد addAccount یک لاگ گذاشتم تا ببینید چه موقع فراخوانی می شود و بدانید اتفاقات این کلاس ارتباط مستقیمی به حساب کاربری دارد. مثلا هرجایی از Account-Manager استفاده کنیم و توسط آن اکانتی را اضافه کنید، متد addAccount در این کلاس فراخوانی می شود. ارتباط این کلاس با Account-manager توسط سرویسی است در پایین می بینید.<br />
سرویس را بصورت زیر بسازید:</p>
<pre class="crayon-plain-tag">public class myService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {

        MyAthenticator authenticator = new MyAthenticator(getBaseContext());
        return authenticator.getIBinder();
    }
}</pre>
<p style="text-align: justify;">حال فایل xml در پوشه xml پروژه بسازید. من اسم این را account_data.xml می گذارم. همانطور که مشاهده می کنید نام برنامه، نوع دلخواه حساب کاربری و آیکون حساب کاربری تعریف می شود. (این آیکون همان آیکونی هست که وقتی از تنظیمات وارد حساب کاربری گوشی می شوید، انواع حساب های کاربری موجود  را با آیکن آنها را می بینید!)</p>
<pre class="crayon-plain-tag">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="ir.mahditajik.testAppAccountType"
    android:icon="@mipmap/ic_launcher"
    android:smallIcon="@mipmap/ic_launcher"
    android:label="@string/app_name"/&gt;</pre>
<p style="text-align: justify;">سپس لازم است تا سرویس تولید شده را در فایل Manifest  تعریف کرده و فایل account_data.xml را ضمیمه کنیم:</p>
<pre class="crayon-plain-tag">&lt;service android:name=".MyService" android:exported="false"&gt;
    &lt;intent-filter&gt;
        &lt;action android:name="android.accounts.AccountAuthenticator"/&gt;
    &lt;/intent-filter&gt;
    &lt;meta-data
        android:name="android.accounts.AccountAuthenticator"
        android:resource="@xml/account_data"/&gt;
&lt;/service&gt;</pre>
<p style="text-align: justify;">حال تنها کاری که باید انجام دهیم استفاده از دستور accountmanageraddAccountExplicitly در هر جای دلخواه است.</p>
<pre class="crayon-plain-tag">public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        if (fab != null)
            fab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    AccountManager accountManager = AccountManager.get(MainActivity.this); //this is Activity
                    Account account = new Account("MyAccount", "com.mahdi");

                    boolean success = accountManager.addAccountExplicitly(account, "password", null);
                    accountManager.setPassword(account, "mahditajik");
                    if (success) {
                        Log.d("mahdi", "Account created");

                    } else {
                        Log.d("mahdi", "Account creation failed. Look at previous logs to investigate");
                    }
                }
            });

    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}</pre>
<p style="text-align: justify;">خیلی خوب! شما موفق شدید با اجرای برنامه و لمس fab button حساب کاربری جدیدی از نوع &#8220;com.mahdi&#8221; ایجاد کنید که در آن نام کاربری و کلمه عبور قرار داده شده است. می توانید به تنظیمات گوشی رفته و حساب کاربری تولید شده را مشاهده کنید. امیدوارم آموزش براتون مفید بوده باشدو  در آموزش بعدی نحوه استفاده از این نام کاربری و کلمه عبور برای لاگین خودکار و همچنین اتفاقات و متد های MyAutenticator را بطور مفصل مورد برسی قرار خواهیم داد. درصورتی که نکته نظر یا سوالی داشتید کامنت کنید.</p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/account-manager/">کار با Account-manager اندروید</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.mahditajik.ir/account-manager/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
