<?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>آموزش &#8211; Mahdi Tajik</title>
	<atom:link href="http://www.mahditajik.ir/category/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, 28 Mar 2019 09:06:47 +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>آموزش &#8211; Mahdi Tajik</title>
	<link>http://www.mahditajik.ir</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Rx java چیست؟ بخش اول</title>
		<link>http://www.mahditajik.ir/rx-java-%da%86%db%8c%d8%b3%d8%aa%d8%9f-%d8%a8%d8%ae%d8%b4-%d8%a7%d9%88%d9%84/</link>
					<comments>http://www.mahditajik.ir/rx-java-%da%86%db%8c%d8%b3%d8%aa%d8%9f-%d8%a8%d8%ae%d8%b4-%d8%a7%d9%88%d9%84/#respond</comments>
		
		<dc:creator><![CDATA[mahdi]]></dc:creator>
		<pubDate>Sun, 24 Mar 2019 10:09:37 +0000</pubDate>
				<category><![CDATA[آموزش]]></category>
		<guid isPermaLink="false">http://www.mahditajik.ir/?p=2637</guid>

					<description><![CDATA[<p>RxJava&#160;کتابخانه ایست برای برنامه نویسی بصورت&#160;Reactive. خود&#160;Reactive Programing&#160;هم میشه اینطور در نظر گرفت که روش برنامه نویسی بر اساس یک واقعه یا&#160;Event&#160;است. نمی دونم چقدر با&#160;Event&#160;و یا&#160;Reactive programing&#160;آشنایی دارید اما اگر بخوام به زبان ساده بگم&#160;Event&#160;&#160;این هست که یک واقعه رخ میده و بعضی کلاس ها و آبجکت ها نسبت به اون واقعه حساسند و ...</p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/rx-java-%da%86%db%8c%d8%b3%d8%aa%d8%9f-%d8%a8%d8%ae%d8%b4-%d8%a7%d9%88%d9%84/">Rx java چیست؟ بخش اول</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></description>
										<content:encoded><![CDATA[
<p><strong>RxJava</strong>&nbsp;کتابخانه ایست برای برنامه نویسی بصورت&nbsp;<strong>Reactive</strong>. خود&nbsp;<strong>Reactive Programing</strong>&nbsp;هم میشه اینطور در نظر گرفت که روش برنامه نویسی بر اساس یک واقعه یا&nbsp;<strong>Event</strong>&nbsp;است. نمی دونم چقدر با&nbsp;<strong>Event</strong>&nbsp;و یا&nbsp;<strong>Reactive programing</strong>&nbsp;آشنایی دارید اما اگر بخوام به زبان ساده بگم&nbsp;<strong>Event&nbsp;</strong>&nbsp;این هست که یک واقعه رخ میده و بعضی کلاس ها و آبجکت ها نسبت به اون واقعه حساسند و متوجه اون واقعه می شوند. فرض کنید بابای خونه نسبت به روشن کردن کولر ( ایونت روشن شدن کولر) حساسه و هروقت اتفاق میافته به محض مطلع شدن عکس العمل مناسب و نشون میده! البته این یک شوخی بود اماواقعیت قضیه همینه.</p>


<p><strong>RxJava</strong> کتابخانه ایست برای برنامه نویسی بصورت <strong>Reactive </strong>در جاوا. خود <strong>Reactive Programing </strong>چیه؟ <strong>Reactive Programing</strong> روش برنامه نویسی بر اساس جریان داده و تغییرات روی آن بر اساس یک واقعه یا <strong>Event</strong> است. نمی دونم چقدر با <strong>Event</strong> و یا <strong>Reactive programing</strong> آشنایی دارید اما اگر بخوام به زبان ساده بگم <strong>Event </strong> این است که یک واقعه رخ می دهد و بعضی کلاس ها و آبجکت ها نسبت به آن واقعه حساسند و متوجه آن می شوند. فرض کنید بابای خونه نسبت به روشن کردن کولر ( ایونت روشن شدن کولر) حساسند و هروقت اتفاق میافتد به محض مطلع شدن عکس العمل مناسب را نشان می دهند! البته این یک شوخی بود اما واقعیت قضیه همین است. در ادامه موضوع رو بیشتر باز می کنم.</p>
<blockquote>
<p><a href="https://github.com/ReactiveX/RxJava" target="_blank" rel="noopener noreferrer">R</a><a href="https://github.com/ReactiveX/RxJava" target="_blank" rel="noopener noreferrer">xJava – Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM.</a></p>
</blockquote>
<p>خیلی خوب، گفتم که  برای برنامه نویسی بصورت <strong>Reactive</strong> در جاوا باید از <strong>RxJava</strong> استفاده کنیم. یک کامینوتی به نام <a href="http://reactivex.io/languages.html" target="_blank" rel="noopener noreferrer"><strong>ReactiveX</strong></a> است که تقریباً برای تمامی  زبان های برنامه نویسی مطرح، کتابخانه داده تا بتوان در آنها از امکانات <strong>Reactive</strong> استفاده کرد. مثلاً <strong>RxKotlin</strong> ،<strong>RxDart</strong> ،<strong>RxScala</strong> ،<strong>RxPHP</strong> و&#8230;. شاید بپرسید پس <strong>RxAndroid</strong> چیه؟ آیا اون هم پیاده سازی <strong>Reactive</strong> در اندرویده؟ اینجا باید بگم خیر!  <a href="https://github.com/ReactiveX/RxAndroid" target="_blank" rel="noopener noreferrer"><strong>RxAndroid</strong> </a>جای گزین <strong>RxJava</strong> برای اندروید نیست. بلکه افزونه ای است متشکل از مجموعه ای از ابزار های <strong>Rx</strong> برای اندروید برای <strong>RxJava</strong> . یعنی ما در اندروید از <strong>RxAndroid</strong> به تنهایی نمی تونیم استفاده کنیم و باید در کنارش حتماً <strong>RxJava</strong> باشه. فکر می کنم در جلسات بعدی که میریم سراع مثال این مسائل این دو وابستگی را در کنار هم در <strong>Gradle</strong> مشاهده خواهید کرد.</p>
<p>پیش نویس این مقاله رو بیش از دو سال پیش شروع کردم. موقعی که هنوز استفاده از <strong>RxJava</strong> و <strong>RxAndroid</strong> خیلی باب نشده بود.  منتهی لازم دیدم که هرچه زود تر به این مبحث بپردازم و تا  سریعتر بتونم وارد مباحث معماری بشم  که خیلی بکارمون میاد و کمکمون می کنه. احتمالاً <strong>RxJava</strong> رو بتونم در دو یا سه جلسه تمومش کنم و امیدوارم براتون مفید باشه.</p>
<p>از تعاریف که بگذریم می رسیم به منطق و مفهوم کار: به نظر خود بنده <strong>Reactive Programming</strong> پیاده سازی <a href="https://en.wikipedia.org/wiki/Observer_pattern" target="_blank" rel="noopener noreferrer"><strong>Observer pattern</strong></a> در سطح برنامه نویسی است. همانطور که در ادامه مشاهده خواهید کرد، یکی از مفاهیمی که بسیارمورد استفاده در <strong>Reactive</strong> هست مفهومی به نام <strong>Observer</strong> یا <strong>نظاره گر</strong> است. پس لازم است که ببینیم این دیزاین پترن دقیقاً چی می خواد بگوید.</p>
<h3>Observer pattern</h3>
<p>داستان اینطوریه که کلاً سه تا مفهوم داریم. یکسری <strong>موضوع </strong>یا <strong>Subject</strong> داریم که <strong>حالت </strong>یا <strong>State</strong> خاص دارند و یک تعدادی <strong>نظاره گر</strong> یا <strong>Observer </strong>هستند که به تغییر <strong>State</strong> این <strong>Subject</strong> ها علاقه مند هستند. پس خود را برای تغیرات حالت موضوع مورد نظر مهیا می کنند و در هر تغییر حالت، این تغییر با مکانیزمی به آنها اطلاع داده شود.</p>


<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="http://www.bitecode.ir/wp-content/uploads/2019/03/OBSERVER-PATTTERN.jpg" alt="" class="wp-image-3959"/></figure></div>



<p>در این مثال ما پدر نسبت به روشن شدن کولر حساس است و تا کولر روشن می شود آن را خاموش می کند. از طرفی روشن شدن کولر برای مادر یا فرزند اهمیتی ندارد. همینطور بوی سوختن غذا فقط برای مادر مهم است و بعد از شنیدن آن به سرعت خودش و به آشپزخانه می رساند، در صورتی که برای پدر و فرزند معنی خاصی ندارد و اصلا متوجهش نیستند. ( البته مثال خیلی انتزاعی است). <strong>RxJava</strong> هم به همین صورت است. یعنی اتفاقات و <strong>event</strong> ها بر اساس وارد شدن و یا تغییر اطلاعات فعال می شوند و یک تعدادی کلاس به آنها واکنش نشان می دهند.</p>



<p>حالا که پترن <strong>Observer</strong> را برسی کردیم می خواهیم مفاهیم متناظر آن در <strong>RxJava</strong> را ببینیم.</p>


<p>برای ملاحظه مقاله کامل به سایت <strong><span style="color: #ff9900;"><a style="color: #ff9900;" href="http://www.bitecode.ir/learning/android/rxjava/" target="_blank" rel="noopener noreferrer">بایت کد</a></span></strong> مراجعه کنید.</p><p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/rx-java-%da%86%db%8c%d8%b3%d8%aa%d8%9f-%d8%a8%d8%ae%d8%b4-%d8%a7%d9%88%d9%84/">Rx java چیست؟ بخش اول</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.mahditajik.ir/rx-java-%da%86%db%8c%d8%b3%d8%aa%d8%9f-%d8%a8%d8%ae%d8%b4-%d8%a7%d9%88%d9%84/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>برنامه اندروید چگونه کامپایل و اجرا می شود</title>
		<link>http://www.mahditajik.ir/%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%a7%d9%86%d8%af%d8%b1%d9%88%db%8c%d8%af-%da%86%da%af%d9%88%d9%86%d9%87-%da%a9%d8%a7%d9%85%d9%be%d8%a7%db%8c%d9%84-%d9%88-%d8%a7%d8%ac%d8%b1%d8%a7-%d9%85%db%8c/</link>
					<comments>http://www.mahditajik.ir/%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%a7%d9%86%d8%af%d8%b1%d9%88%db%8c%d8%af-%da%86%da%af%d9%88%d9%86%d9%87-%da%a9%d8%a7%d9%85%d9%be%d8%a7%db%8c%d9%84-%d9%88-%d8%a7%d8%ac%d8%b1%d8%a7-%d9%85%db%8c/#respond</comments>
		
		<dc:creator><![CDATA[mahdi]]></dc:creator>
		<pubDate>Sat, 07 Jul 2018 22:28:16 +0000</pubDate>
				<category><![CDATA[آموزش]]></category>
		<category><![CDATA[apk]]></category>
		<category><![CDATA[بایت کد]]></category>
		<category><![CDATA[کامپایلر]]></category>
		<guid isPermaLink="false">http://www.mahditajik.ir/?p=2862</guid>

					<description><![CDATA[<p>بسمه تعالی در این جلسه قصد داریم با نحوه ساخته شدن و اجرا شدن برنامه اندروید آشنا شویم.  اول از همه اصطلاح &#8220;کامپایل&#8221; شدن را تعریف می کنیم. در این باره pc mag staff می گوید: A compiler is computer software that transforms computer code written in one programming language (the source language) into another ...</p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%a7%d9%86%d8%af%d8%b1%d9%88%db%8c%d8%af-%da%86%da%af%d9%88%d9%86%d9%87-%da%a9%d8%a7%d9%85%d9%be%d8%a7%db%8c%d9%84-%d9%88-%d8%a7%d8%ac%d8%b1%d8%a7-%d9%85%db%8c/">برنامه اندروید چگونه کامپایل و اجرا می شود</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></description>
										<content:encoded><![CDATA[<p>بسمه تعالی</p>
<p>در این جلسه قصد داریم با نحوه ساخته شدن و اجرا شدن برنامه اندروید آشنا شویم.  اول از همه اصطلاح &#8220;کامپایل&#8221; شدن را تعریف می کنیم. در این باره <strong>pc mag staff</strong> می گوید:</p>
<blockquote><p>A <b>compiler</b> is <a class="mw-redirect" title="Computer software" href="https://en.wikipedia.org/wiki/Computer_software">computer software</a> that transforms computer code written in one <a title="Programming language" href="https://en.wikipedia.org/wiki/Programming_language">programming language</a> (the source language) into another programming language (the target language). Compilers are a type of <a title="Translator (computing)" href="https://en.wikipedia.org/wiki/Translator_(computing)">translator</a> that support digital devices, primarily computers. The name <i>compiler</i> is primarily used for programs that translate <a title="Source code" href="https://en.wikipedia.org/wiki/Source_code">source code</a> from a <a title="High-level programming language" href="https://en.wikipedia.org/wiki/High-level_programming_language">high-level programming language</a> to a <a class="mw-redirect" title="Lower level language" href="https://en.wikipedia.org/wiki/Lower_level_language">lower level language</a> (e.g., <a title="Assembly language" href="https://en.wikipedia.org/wiki/Assembly_language">assembly language</a>, <a title="Object code" href="https://en.wikipedia.org/wiki/Object_code">object code</a>, or <a title="Machine code" href="https://en.wikipedia.org/wiki/Machine_code">machine code</a>) to create an <a title="Executable" href="https://en.wikipedia.org/wiki/Executable">executable</a> program.</p></blockquote>
<p>&nbsp;</p>
<p>کامپایل شدن به معنای کنارهم قرار دادن و تبدیل کدهای و منابع برنامه و ساخت فایلی قابل اجرا برای دستگاه مقصد است. به برنامه ای که این کار را انجام می دهد کامپایلر گفته می شود. ممکن است برنامه ای برای محیط ویندوز کامپایل شود ( برنامه های ویندوزی) و یا برای اندروید کامپایل شود. ( برنامه های اندرویدی) اما هرکدام دارای شرایط و فرمت خاصی هستند که کامپایلر آن را کنترل می کند. برای استفاده از کامپایلر های مختلف برنامه ها و ابزار توسعه خاص مورد نیاز است. به عنوان مثال برای کامپایل کردن برنامه های اندرویدی می توان از Ecilipes یا Android studio و Intellij IDEA و غیره استفاده کرد. برای ساخت و کامپایل برنامه های ویندوزی از Visual Studio، Borland delphi و غیره استفاده کرد. بحث اصلی ما در مورد کامپایل برنامه اندروید است&#8230;</p>
<p><a href="http://www.bitecode.ir/learning/android/%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%a7%d9%86%d8%af%d8%b1%d9%88%db%8c%d8%af-%da%86%da%af%d9%88%d9%86%d9%87-%da%a9%d8%a7%d9%85%d9%be%d8%a7%db%8c%d9%84-%d9%88-%d8%a7%d8%ac%d8%b1%d8%a7-%d9%85%db%8c/" target="_blank" rel="noopener"><strong><span style="color: #ff9900;">برای دیدن مقاله کامل به سایت بایت کد مراجعه کنید.</span></strong></a></p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%a7%d9%86%d8%af%d8%b1%d9%88%db%8c%d8%af-%da%86%da%af%d9%88%d9%86%d9%87-%da%a9%d8%a7%d9%85%d9%be%d8%a7%db%8c%d9%84-%d9%88-%d8%a7%d8%ac%d8%b1%d8%a7-%d9%85%db%8c/">برنامه اندروید چگونه کامپایل و اجرا می شود</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.mahditajik.ir/%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%a7%d9%86%d8%af%d8%b1%d9%88%db%8c%d8%af-%da%86%da%af%d9%88%d9%86%d9%87-%da%a9%d8%a7%d9%85%d9%be%d8%a7%db%8c%d9%84-%d9%88-%d8%a7%d8%ac%d8%b1%d8%a7-%d9%85%db%8c/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>تفاوت Handler و Thread و AsyncTask در اندروید</title>
		<link>http://www.mahditajik.ir/%d8%aa%d9%81%d8%a7%d9%88%d8%aa-handler-%d9%88-thread-%d9%88-asynctask-%d8%af%d8%b1-%d8%a7%d9%86%d8%af%d8%b1%d9%88%db%8c%d8%af/</link>
					<comments>http://www.mahditajik.ir/%d8%aa%d9%81%d8%a7%d9%88%d8%aa-handler-%d9%88-thread-%d9%88-asynctask-%d8%af%d8%b1-%d8%a7%d9%86%d8%af%d8%b1%d9%88%db%8c%d8%af/#comments</comments>
		
		<dc:creator><![CDATA[mahdi]]></dc:creator>
		<pubDate>Tue, 30 Jan 2018 16:33:14 +0000</pubDate>
				<category><![CDATA[آموزش]]></category>
		<category><![CDATA[AsyncTask]]></category>
		<category><![CDATA[Handler]]></category>
		<category><![CDATA[Thread]]></category>
		<guid isPermaLink="false">http://www.mahditajik.ir/?p=2728</guid>

					<description><![CDATA[<p>با سلام، ممکنه برای خیلی ها این سوال پیش اومده باشه که از هرکدوم از Handler یا Thread یا AsycTask استفاده کرده باشیم و لی در حقیقت تفاوت میان آنها را به درستی نشناسیم. در این مقاله می خواهیم این تفاوت ها و محل مناسب استفاده از هر یک را برسی کنیم. اول لازم هست ...</p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/%d8%aa%d9%81%d8%a7%d9%88%d8%aa-handler-%d9%88-thread-%d9%88-asynctask-%d8%af%d8%b1-%d8%a7%d9%86%d8%af%d8%b1%d9%88%db%8c%d8%af/">تفاوت Handler و Thread و AsyncTask در اندروید</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 wp-image-2731 size-full" src="http://www.mahditajik.ir/wp-content/uploads/2018/01/asynctask.jpg" alt="AsyncTask" width="800" height="486" srcset="http://www.mahditajik.ir/wp-content/uploads/2018/01/asynctask.jpg 800w, http://www.mahditajik.ir/wp-content/uploads/2018/01/asynctask-300x182.jpg 300w, http://www.mahditajik.ir/wp-content/uploads/2018/01/asynctask-768x467.jpg 768w" sizes="(max-width: 800px) 100vw, 800px" /></p>
<p style="text-align: justify;">با سلام، ممکنه برای خیلی ها این سوال پیش اومده باشه که از هرکدوم از <strong>Handler</strong> یا <strong>Thread</strong> یا <strong>AsycTask</strong> استفاده کرده باشیم و لی در حقیقت تفاوت میان آنها را به درستی نشناسیم. در این مقاله می خواهیم این تفاوت ها و محل مناسب استفاده از هر یک را برسی کنیم.</p>
<p style="text-align: justify;">اول لازم هست تا با تعریف هرکدام بیشتر آشنا شویم.</p>
<p style="text-align: right;"><strong>Thread</strong></p>
<blockquote>
<p style="text-align: left;">A thread is a thread of execution in a program. The Java Virtual Machine allows an application to have multiple threads of execution running concurrently.</p>
</blockquote>
<p style="text-align: justify;">ترد یا رشته واحد های کلی پردازش وظایف هستند که هر برنامه می تواند تعدادی ترد داشته باشد. هر ترد اولویتی در سیستم دارد و تردهای ایجاد شده توسط یک ترد دیگر، اولویت هم سطح خواهند داشت. در اندروید هر برنامه یک ترد اصلی یا <strong>Main thread</strong> دارد و وقتی  <strong>thread</strong> جدیدی ایجاد می کنیم پردازش ها جدا از اتفاقات ترد اصلی روی می دهد. اما برای هماهنگ کردن و یا به عنوان مثال بازگشت جواب باید اینکار را بصورت دستی توسط <strong>message</strong> یا <strong>callback</strong> مدیریت کنیم. ( <a href="http://www.mahditajik.ir/%d9%86%d8%ad%d9%88%d9%87-%d8%a7%d8%b1%d8%aa%d8%a8%d8%a7%d8%b7-%d8%a8%db%8c%d9%86-thread-%d9%87%d8%a7/" target="_blank" rel="noopener"><span style="color: #3366ff;">مقاله کامل در اینجا</span></a>) در صورتی که اگر تردی ایجاد کنیم دستورالعمل های آن باعث freeze شدن برنامه نمی شود زیرا در یک ترد دیگری جاریست اما در عوض به عناصر <strong>UI</strong> که در ترد اصلی هستند دسترسی نداریم و نمی توانیم بطور مستقیم <strong>UI</strong> را تغییر دهیم.</p>
<p></p><pre class="crayon-plain-tag">new Thread(new Runnable() {
    @Override
    public void run() {
        doSomething();
    }
}).start();</pre><p></p>
<p style="text-align: right;"><strong>Handler</strong></p>
<blockquote>
<p style="text-align: left;">A Handler allows you to send and process Message and Runnable objects associated with a thread&#8217;s MessageQueue. Each Handler instance is associated with a single thread and that thread&#8217;s message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it &#8212; from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue</p>
</blockquote>
<p style="text-align: justify;">طبق تعریف خود گوگل با تعریف یک هندلر می توانیم پیغام یا <strong>Runnable</strong> ای را پردازش کنیم که دقیقاً در thread  کلاس تولید کننده آن قرار می گیرد و نحوه اجرا شدن آن هم به صف همان <strong>thread</strong> بستگی دارد. پس یعنی <strong>Handler</strong> های تولید شده در یک <strong>thread</strong> به ترتیب در همان <strong>thread</strong> اجرا می شوند. دستورالعمل هایی که در <strong>Handler</strong> اجرا می شوند در <strong>thread</strong> اصلی بوده و اصطلاحاً باعث  freeze  شدن برنامه می شود. اما اگر در ترد اصلی تولید شوند به عناصر UI برنامه دسترسی داریم و مثلا می توانیم یک <strong>ViewText</strong> ای را بروز رسانی کنیم.</p>
<p></p><pre class="crayon-plain-tag">new Handler().post(new Runnable() {
    @Override
    public void run() {
       doSomething();
    }
});</pre><p></p>
<p style="text-align: justify;">بطور معمول وقتی از <strong>Handler</strong> استفاده می کنیم که بخواهیم اتفاق خاصی در زمان خاصی بیافتد. مثلا فرض کنید می خواهید با تایمر <strong>View</strong> ای را آپدیت کنید.</p>
<p></p><pre class="crayon-plain-tag">new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        // update UI after 1000 millisecons
    }
},1000);</pre><p><strong>Runable</strong></p>
<p>یک اینترفیسی است که تمامی کلاس هایی که قرار است توسط  <strong>Thread </strong>اجرا شوند، باید آن را پیاده سازی کنند که یک متد <strong>run </strong>دارد. پس هرکلاس مشخص می کند که هنگام اجرا شدن توسط Thread چکاری را انجام دهد. ( آن کار در متد run پیاده سازی می شود.) که در تمامی مثال های قبلی قابل مشاهده است.</p>
<p><strong>AsyncTask</strong></p>
<p>برای ساخت آن باید کلاسی از آن مشتق کنیم و متد های آن را <strong>Override</strong> کنیم.</p>
<ul>
<li>doInBackground</li>
<li>onPostExecute</li>
</ul>
<p style="text-align: justify;">متد <strong>doInBackground</strong> در یک ترد مجزا انجام می گیرد و جواب آن <strong>onPostExecute</strong> در ترد اصلی یا همان <strong>UI thread</strong> اتفاق می افتد که می توانیم توسط آن <strong>UI</strong> را آپدیت کنیم. البته متد های دیگری نیز دارد که تنها به این دو متد اشاره کردم. استفاده از <strong>AsyncTask</strong> بسیار در گرفتن اطلاعات از سمت <strong>web</strong> پرکاربرد است. ( در صورتی که نخواهیم از کتابخانه های نظیر Retrofit و Volley استفاده کنیم) و اصولاً در قدیم (حدود ۶ سال قبل) ترکیب <strong>HttpConnection</strong> و <strong>AsyncTask</strong> برای صدا زدن <strong>Api</strong> های سمت وب اجتناب ناپذیر بود!</p>
<p></p><pre class="crayon-plain-tag">private class MyAsycTask extends AsyncTask&lt;Void, Void, Void&gt; {

    @Override
    protected void onPreExecute() {
       //do something in Ui-thread before background work start
    }

    @Override
    protected Void doInBackground(Void... params) {
       //do something in background
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
      //do something in Ui-thread
    }
}</pre><p></p>
<p style="text-align: justify;"><strong>نکته:</strong></p>
<p>یک نوع استفاده دیگر از Handler وجود دارد که در ظاهر انگار  Thread است اما:</p><pre class="crayon-plain-tag">runOnUiThread(new Runnable() {
    @Override
    public void run() {
        doSomething();
    }
});</pre><p>توجه کنید که <strong>runOnUiThread</strong> یک نوع خاصی از <strong>Handler</strong> است که فقط در ترد اصلی اتفاق می افتد.</p>
<p>هرگونه سوال و یا نکته ای داشتید خوشحال می شم که کامنت کنید.</p>
<p>منبع: <a href="http://www.biitecode.ir" target="_blank" rel="noopener">بایت کد</a></p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/%d8%aa%d9%81%d8%a7%d9%88%d8%aa-handler-%d9%88-thread-%d9%88-asynctask-%d8%af%d8%b1-%d8%a7%d9%86%d8%af%d8%b1%d9%88%db%8c%d8%af/">تفاوت Handler و Thread و AsyncTask در اندروید</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.mahditajik.ir/%d8%aa%d9%81%d8%a7%d9%88%d8%aa-handler-%d9%88-thread-%d9%88-asynctask-%d8%af%d8%b1-%d8%a7%d9%86%d8%af%d8%b1%d9%88%db%8c%d8%af/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>نحوه ارتباط بین thread ها</title>
		<link>http://www.mahditajik.ir/%d9%86%d8%ad%d9%88%d9%87-%d8%a7%d8%b1%d8%aa%d8%a8%d8%a7%d8%b7-%d8%a8%db%8c%d9%86-thread-%d9%87%d8%a7/</link>
					<comments>http://www.mahditajik.ir/%d9%86%d8%ad%d9%88%d9%87-%d8%a7%d8%b1%d8%aa%d8%a8%d8%a7%d8%b7-%d8%a8%db%8c%d9%86-thread-%d9%87%d8%a7/#comments</comments>
		
		<dc:creator><![CDATA[mahdi]]></dc:creator>
		<pubDate>Mon, 29 Jan 2018 10:51:58 +0000</pubDate>
				<category><![CDATA[آموزش]]></category>
		<category><![CDATA[Handler]]></category>
		<category><![CDATA[runnable]]></category>
		<category><![CDATA[Thread]]></category>
		<guid isPermaLink="false">http://www.mahditajik.ir/?p=2741</guid>

					<description><![CDATA[<p>thread یا رشته عبارتند از  واحد های کلی پردازش وظایف که هر برنامه می تواند تعدادی ترد داشته باشد. هر ترد اولویتی در سیستم دارد و تردهای ایجاد شده توسط یک ترد دیگر، اولویت هم سطح خواهند داشت. در اندروید هر برنامه یک ترد اصلی یا Main thread دارد و وقتی  thread جدیدی ایجاد می ...</p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/%d9%86%d8%ad%d9%88%d9%87-%d8%a7%d8%b1%d8%aa%d8%a8%d8%a7%d8%b7-%d8%a8%db%8c%d9%86-thread-%d9%87%d8%a7/">نحوه ارتباط بین thread ها</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-2755" src="http://www.mahditajik.ir/wp-content/uploads/2018/01/thread.jpg" alt="" width="800" height="486" srcset="http://www.mahditajik.ir/wp-content/uploads/2018/01/thread.jpg 800w, http://www.mahditajik.ir/wp-content/uploads/2018/01/thread-300x182.jpg 300w, http://www.mahditajik.ir/wp-content/uploads/2018/01/thread-768x467.jpg 768w" sizes="(max-width: 800px) 100vw, 800px" /></p>
<p style="text-align: justify;">thread یا رشته عبارتند از  واحد های کلی پردازش وظایف که هر برنامه می تواند تعدادی ترد داشته باشد. هر ترد اولویتی در سیستم دارد و تردهای ایجاد شده توسط یک ترد دیگر، اولویت هم سطح خواهند داشت. در اندروید هر برنامه یک ترد اصلی یا <strong>Main thread</strong> دارد و وقتی  <strong>thread</strong> جدیدی ایجاد می کنیم پردازش ها جدا از اتفاقات ترد اصلی روی می دهد. اما برای هماهنگ کردن و یا به عنوان مثال بازگشت جواب باید اینکار را بصورت دستی توسط <strong>message</strong> یا <strong>callback</strong> مدیریت کنیم.</p>
<p style="text-align: justify;">در این مقاله می خواهیم نحوه ارتباط با این دو روش را برسی کنیم.</p>
<p><strong>message</strong></p>
<p style="text-align: justify;">اصلی ترین راه ارتباط بین تردها پاس دادن پیام است. تردی که قرار است پیغام را دریافت کند باید دسترسی به صف پیغام ها داشته باشد که  messageQueue است و خود ترد ساده فاقد این کلاس است.</p>
<p></p><pre class="crayon-plain-tag">new Thread(new Runnable() {
    @Override
    public void run() {
        doSomething();
    }
}).start();</pre><p></p>
<p style="text-align: justify;">به شکل thread ساده و بدون messageQueue توجه کنید:</p>
<p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2743" src="http://www.mahditajik.ir/wp-content/uploads/2018/01/Th_JAT.png" alt="" width="200" height="141" /></p>
<p style="text-align: justify;">برای افزودن messageQueue از کلاس Looper استفاده می کنیم که messageQueue را برایمان فراهم می کند.</p>
<p></p><pre class="crayon-plain-tag">new Thread(new Runnable() {
    @Override
    public void run() {
        Looper.prepare();
        doSomething();
        Looper.loop();
    }
}).start();</pre><p></p>
<p style="text-align: justify;">و بدین ترتیب messageQueue برایمان محیا می شود.</p>
<p style="text-align: justify;"><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2744" src="http://www.mahditajik.ir/wp-content/uploads/2018/01/Th_TWL.png" alt="" width="320" height="156" srcset="http://www.mahditajik.ir/wp-content/uploads/2018/01/Th_TWL.png 320w, http://www.mahditajik.ir/wp-content/uploads/2018/01/Th_TWL-300x146.png 300w" sizes="(max-width: 320px) 100vw, 320px" /></p>
<p style="text-align: justify;">حال تردی که می خواهد مسیج ارسال کند نیاز به یک <strong>Handler</strong> دارد. وظیفه Handler ارسال و پردازش پیغام مربوط به messageQueue ترد ساخته شده اش می باشد. ( همچنین اجرای Runnable که موضوع این آموزش نیست). وقتی یک Handler جدید می سازیم به threadhd ای که درون آن ساخته شده و messageQueue مربوطه متصل می شود و message ها و runnable ها را به messageQueue مربوطه می رساند و یا از روی آن اجرا می کند. در اینجا برای ارسال پیام کافیست که یک هندلر بصورتی تعریف کنیم هردو ترد دسترسی داشته باشند ( بصورت public یا پاس دادن بصورت properties) در یکی توسط آن Messagehvshg ارسال کنیم و در دیگری Message را گرفته و پردازش کنیم.</p>
<p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2745" src="http://www.mahditajik.ir/wp-content/uploads/2018/01/Th_PAT.png" alt="" width="320" height="163" srcset="http://www.mahditajik.ir/wp-content/uploads/2018/01/Th_PAT.png 320w, http://www.mahditajik.ir/wp-content/uploads/2018/01/Th_PAT-300x153.png 300w" sizes="(max-width: 320px) 100vw, 320px" /></p>
<p style="text-align: justify;">به مثال ذیل توجه کنید:</p>
<p></p><pre class="crayon-plain-tag">private void testThreadMessaging() {

    Handler handler;

    new Thread(new Runnable() {
        @Override
        public void run() {
            Looper.prepare();

            handler = new Handler(){

                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    Toast.makeText(MainActivity.this, "Job finish with ( "+(float) msg.getData().getLong("jobTime")/1000+" ) seconds", Toast.LENGTH_SHORT)
                            .show();


                }
            };
            Looper.loop();
        }
    }).start();

    new Thread(new Runnable() {
        @Override
        public void run() {
            long jobTime = doSomething(ITERATION_COUNT);
            Message message = new Message();
            Bundle bundle = new Bundle();
            bundle.putLong("jobTime",jobTime);
            message.setData(bundle);
            handler.sendMessage(message);

        }
    }).start();
}</pre><p></p><pre class="crayon-plain-tag">private long doSomething(int iteration) {
    long startTime = System.currentTimeMillis();
    for (int i = 0; i &lt; iteration; i++) {
        Log.i("mahdi", "run: "+i);
    }
    long endTime = System.currentTimeMillis();

    return endTime - startTime ;
}</pre><p></p>
<p style="text-align: justify;">ترد اول بعد از تمام شدن کارش زمان انجام کار را به ترد دوم پاس می دهد. در اینجا handler بصورت public تعریف شده بود.</p>
<p><strong>Callback</strong></p>
<p style="text-align: justify;">در این روش ارتباط از طریق پاس دادن یک اینترفیس انجام می شود. برای اینکه مثال فرق کند ترد دریافت کننده پیام را در Ui thread قرار دادم. ( یعنی ترد جدیدی نساختم و در یک جایی در اکتیویتی تعریف کردم که می دانیم خود اکتیوتی در main thread یا همان Ui thread است).</p>
<p></p><pre class="crayon-plain-tag">private void testThreadCallBack(){

    //our receiver thread is main thread
    callBack = new ThreadCallBack() {
        @Override
        public void onMessage(Object o) {
            Log.i("mahdi", "Job finish with ( "+((Bundle) o).getLong("jobTime")/1000+" ) seconds");

        }
    };

    new Thread(new Runnable() {
        @Override
        public void run() {
            long jobTime = doSomething(ITERATION_COUNT);
            Bundle bundle = new Bundle();
            bundle.putLong("jobTime",jobTime);
            callBack.onMessage(bundle);
        }
    }).start();
}

interface ThreadCallBack{

    void onMessage(Object o);

}</pre><p></p>
<p style="text-align: justify;">برای درک بهتر کدها را اجرا کنید و نتایج را برسی کنید. در صورتی که سوال یا نکته ای داشتید کامنت کنید.</p>
<p>منبع: <a href="http://www.biitecode.ir" target="_blank" rel="noopener">بایت کد</a></p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/%d9%86%d8%ad%d9%88%d9%87-%d8%a7%d8%b1%d8%aa%d8%a8%d8%a7%d8%b7-%d8%a8%db%8c%d9%86-thread-%d9%87%d8%a7/">نحوه ارتباط بین thread ها</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.mahditajik.ir/%d9%86%d8%ad%d9%88%d9%87-%d8%a7%d8%b1%d8%aa%d8%a8%d8%a7%d8%b7-%d8%a8%db%8c%d9%86-thread-%d9%87%d8%a7/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
			</item>
		<item>
		<title>tailrec در Kotlin چیست؟</title>
		<link>http://www.mahditajik.ir/tailrec-%d8%af%d8%b1%da%a9%d8%a7%d8%aa%d9%84%db%8c%d9%86-%da%86%db%8c%d8%b3%d8%aa/</link>
					<comments>http://www.mahditajik.ir/tailrec-%d8%af%d8%b1%da%a9%d8%a7%d8%aa%d9%84%db%8c%d9%86-%da%86%db%8c%d8%b3%d8%aa/#respond</comments>
		
		<dc:creator><![CDATA[mahdi]]></dc:creator>
		<pubDate>Sun, 03 Dec 2017 07:29:52 +0000</pubDate>
				<category><![CDATA[آموزش]]></category>
		<category><![CDATA[#تابع]]></category>
		<category><![CDATA[#کاتلین]]></category>
		<category><![CDATA[fun]]></category>
		<category><![CDATA[kotlin]]></category>
		<category><![CDATA[tailrec]]></category>
		<guid isPermaLink="false">http://www.mahditajik.ir/?p=2701</guid>

					<description><![CDATA[<p>امکانات بسیار زیادی در Kotlin قرار گرفته تا بتواند به زبان رسمی Android مبدل گردد. tailrec یکی از آنهاست. این امکان در توابع بازگشتی کاربرد دارد. همانطور که می دانید استفاده از توابع بازگشتی معمولاً روشی نا صحصیح است که با مقیم شدن در حافظه تا تمام شدن تمامی مراحل، می تواند باعث stack overflow ...</p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/tailrec-%d8%af%d8%b1%da%a9%d8%a7%d8%aa%d9%84%db%8c%d9%86-%da%86%db%8c%d8%b3%d8%aa/">tailrec در Kotlin چیست؟</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-2704" src="http://www.mahditajik.ir/wp-content/uploads/2017/12/tailrec.jpg" alt="" width="800" height="486" srcset="http://www.mahditajik.ir/wp-content/uploads/2017/12/tailrec.jpg 800w, http://www.mahditajik.ir/wp-content/uploads/2017/12/tailrec-300x182.jpg 300w, http://www.mahditajik.ir/wp-content/uploads/2017/12/tailrec-768x467.jpg 768w" sizes="(max-width: 800px) 100vw, 800px" />امکانات بسیار زیادی در <strong>Kotlin</strong> قرار گرفته تا بتواند به زبان رسمی <strong>Android</strong> مبدل گردد. <strong>tailrec</strong> یکی از آنهاست. این امکان در توابع بازگشتی کاربرد دارد. همانطور که می دانید استفاده از توابع بازگشتی معمولاً روشی نا صحصیح است که با مقیم شدن در حافظه تا تمام شدن تمامی مراحل، می تواند باعث <strong>stack overflow</strong> گردد و در طراحی الگوریتم روشی <strong>brutal</strong> است. این امکان وجود دارد تا توابع برگشتی را با استفاده از حلقه بهینه کرد.</p>
<p style="text-align: justify;">با گذاشتن <strong>tailrec</strong> در اول تابع بازگشتی، <strong>kotlin</strong> خودش آن را هنگام کامپایل کردن در صورت برقرار بودن شرایط، پیاده سازی آن تابع را با حلقه انجام داده و کد را بهینه می کند. به عنوان نمونه به تابع فاکتوریل زیر توجه کنید:</p>
<p></p><pre class="crayon-plain-tag">fun fact(x: Long): Long {
    tailrec fun factTail(y: Long, z: Long): Long {
        return if (y == 0L) z
        else {
            return factTail(y - 1, y * z)
        }
    }
    return factTail(x, 1)
}</pre><p></p>
<p style="text-align: justify;">برای صدا زدن کافیست:</p>
<p></p><pre class="crayon-plain-tag">logg("$5! : ${fact(5)}")</pre><p></p>
<p style="text-align: justify;">استفاده از <strong>tailrec</strong> شرایط دارد از قبیل اینکه بعد از صدا زدن <strong>recursive</strong> نباید متد دیگری وجود داشته باشد و یا مثلا اینکه درون بلاک های<strong> try/catch/finally</strong> نمی توان استفاده کرد. مثال کامل <strong>Kotlin</strong> را می توانید در لینک ذیل مشاهده کنید.</p>
<p><a href="https://github.com/mahdit83/KotlinExample" 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>منبع: <span style="color: #ff9900;"><a style="color: #ff9900;" href="http://www.biitecode.ir" target="_blank" rel="noopener">بایت کد</a></span></p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/tailrec-%d8%af%d8%b1%da%a9%d8%a7%d8%aa%d9%84%db%8c%d9%86-%da%86%db%8c%d8%b3%d8%aa/">tailrec در Kotlin چیست؟</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.mahditajik.ir/tailrec-%d8%af%d8%b1%da%a9%d8%a7%d8%aa%d9%84%db%8c%d9%86-%da%86%db%8c%d8%b3%d8%aa/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>مزایا و نحوه استفاده از Product Flavors در Gradle</title>
		<link>http://www.mahditajik.ir/gradle-product-flavors/</link>
					<comments>http://www.mahditajik.ir/gradle-product-flavors/#comments</comments>
		
		<dc:creator><![CDATA[mahdi]]></dc:creator>
		<pubDate>Sun, 24 Sep 2017 09:54:28 +0000</pubDate>
				<category><![CDATA[آموزش]]></category>
		<category><![CDATA[android studio]]></category>
		<category><![CDATA[anotation]]></category>
		<category><![CDATA[build]]></category>
		<category><![CDATA[flavor]]></category>
		<category><![CDATA[gradle]]></category>
		<guid isPermaLink="false">http://www.mahditajik.ir/?p=2562</guid>

					<description><![CDATA[<p>Product Flavor به معنی عطر و طعم محصول است و استفاده از آن امکانات بسیار را به ما در Build گرفتن از پروژه می دهد. خود بخش defaultConfig در  gradle که اطلاعات مربوط به کمترین sdk، نام پکیج و غیره را وارد می کنیم، خود یک کلاس flavor است. با استفاده از flavor امکانات زیادی ...</p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/gradle-product-flavors/">مزایا و نحوه استفاده از Product Flavors در Gradle</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-2615" src="http://www.mahditajik.ir/wp-content/uploads/2017/09/flavor_banner-1.jpg" alt="" width="800" height="486" srcset="http://www.mahditajik.ir/wp-content/uploads/2017/09/flavor_banner-1.jpg 800w, http://www.mahditajik.ir/wp-content/uploads/2017/09/flavor_banner-1-300x182.jpg 300w, http://www.mahditajik.ir/wp-content/uploads/2017/09/flavor_banner-1-768x467.jpg 768w" sizes="(max-width: 800px) 100vw, 800px" /></p>
<p style="text-align: justify;"><strong>Product Flavor</strong> به معنی عطر و طعم محصول است و استفاده از آن امکانات بسیار را به ما در Build گرفتن از پروژه می دهد. خود بخش <strong>defaultConfig</strong> در  <strong>gradle</strong> که اطلاعات مربوط به کمترین sdk، نام پکیج و غیره را وارد می کنیم، خود یک کلاس flavor است. با استفاده از flavor امکانات زیادی می توان به برنامه اضافه کرد، از قبیل minSdk, applicationId, targertSdkVersion  و کلاً تمام تنظیماتی که در بخش defaultConfig می نویسیم. حتی می توانید نسخه دیگری از برنامه با package دیگر را به کمک آن بدون نیاز به تکثیر کلاس ها داشته باشیم.</p>
<blockquote><p>Creating product flavors is similar to creating build types: add them to the <em>productFlavors</em> block and configure the settings you want. The product flavors support the same properties as defaultConfig —this is because <em>defaultConfig</em> actually belongs to the <a href="http://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.ProductFlavor.html" target="_blank" rel="noopener"><em>ProductFlavor </em></a>class. This means you can provide the base configuration for all flavors in the defaultConfig block, and each flavor can change any of these default values, such as the <em>applicationId</em>.</p></blockquote>
<p style="text-align: justify;">فرض کنید می خواهیم برنامه را در دو نسخه رایگان و پولی تهیه کنید که هرکدام دارای پکیج جداگانه است و می توانند همزمان روی گوشی نصب شوند. اگر این امکان یعنی <strong>flavor</strong> در <strong>gradle</strong> وجود نداشت باید دو پروژه با نام پکیج های مختلف ایجاد می کردیم. اما به کمک <strong>Flavor</strong> به راحتی می توان این کار را انجام داد. برای اضافه کردن flavor می توان از منوی بالا <strong>Build/Edit flavors</strong> اقدام کرد و یا بصورت دستی نام و مشخصات موردنیاز را در <strong>gradle</strong> سطح ماژول اضافه کرد.</p>
<p></p><pre class="crayon-plain-tag">productFlavors {
    primary {
        applicationId "ir.mtajik.negin"
    }

    freeVersion {
        applicationId "ir.mtajik.negin.freeVersion"
    }
}</pre><p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2589" src="http://www.mahditajik.ir/wp-content/uploads/2017/09/flavor2.jpg" alt="" width="1033" height="993" srcset="http://www.mahditajik.ir/wp-content/uploads/2017/09/flavor2.jpg 1033w, http://www.mahditajik.ir/wp-content/uploads/2017/09/flavor2-300x288.jpg 300w, http://www.mahditajik.ir/wp-content/uploads/2017/09/flavor2-768x738.jpg 768w, http://www.mahditajik.ir/wp-content/uploads/2017/09/flavor2-1024x984.jpg 1024w" sizes="(max-width: 1033px) 100vw, 1033px" /></p>
<p style="text-align: justify;">ما دو <strong>flavor</strong> ساختیم که اطلاعات پیش فرض خود را از <strong>DefaultConfig </strong> می گیرد. ما به  <strong>gradle</strong> گفتیم که در نسخه رایگان نام پکیج را تغییر دهد. در صورت انتخاب هرکدام و <strong>Build</strong> گرفتن، خود <strong>gradle</strong> اتومات پکیج مورد نظر را تولید می کند و لازم نیست دستی اینکار را انجام دهیم. حال فرض کنید که لازم است در نسخه رایگان در یکسری از کلاس ها اتفاقات دیگری بیافتد. برای اینکار لازم نیست  کلاس های مجزا (ولی همنام) را جداگانه برای هر <strong>flavor</strong> ایجاد کنیم. کافیست در هر کلاس که قرار است با توجه به flavor اتفاق خاصی بیافتد، بصورت زیر چک کنیم:</p>
<p></p><pre class="crayon-plain-tag">if(BuildConfig.FLAVOR.equals("freeVersion")){
    //do something
}</pre><p></p>
<p style="text-align: justify;">از طرفی اگر قرار است با توجه به <strong>flavor</strong> های گوناگون تغییری در <strong>resource</strong> ها داشته باشیم در این صورت باید فایل مربوط به آن را در پکیج همنام <strong>flavor</strong> ساخته شده قرار دهیم. مثلا فرض کنید قرار است در  <strong>freeVersion </strong>نام برنامه متفاوت بوده و صفحه اصلی برنامه کلاً فرق داشته باشد و همچنین دیتابیس Sqlite همراه پروژه نیز متفاوت باشد. (یعنی نمی خواهیم این تغییرات را از درون کد انجام دهیم بلکه می خواهیم خودش بطور خودکار resource مربوطه را استفاده کند! ) پس باید پکیج جدید را به همراه فایل های مورد نیاز که قرار است جایگزین شود بسازیم. یادتان باشد این قضیه فقط در مورد Resource ها می باشد و در کلاس ها ایجاد کلاس تکراری بخاطر اندک تفاوت درست نیست و افزونگی ایجاد می کند، بلکه همانطور که گفتم بهتر است با یک if ساده، اتفاقات مربوط به این flavor را در همان یک کلاس هندل کنید. حتماً توجه دارید که این قضیه در مورد کلاس های متفاوت صدق نمی کند ( قرار است یک کلاس خاصی در یک flavor خاصی وجود داشته باشد!)  و باید کلاس های متفاوت اضافه شوند. در تصویر زیر نحوه و محل ساخت قایل های flavor نمایش داده ام:</p>
<p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2588" src="http://www.mahditajik.ir/wp-content/uploads/2017/09/flavor1.jpg" alt="" width="324" height="467" srcset="http://www.mahditajik.ir/wp-content/uploads/2017/09/flavor1.jpg 324w, http://www.mahditajik.ir/wp-content/uploads/2017/09/flavor1-208x300.jpg 208w" sizes="(max-width: 324px) 100vw, 324px" /></p>
<p style="text-align: justify;">یک پکیج همنام با  <strong>flavor</strong> ایجاد شده موازی  <strong>main</strong>  در  <strong>gem/src/main</strong> . پس دیدیم که تمامی Resource هایی که قرار بود متفاوت باشند را قرار دادیم. از جمله DB، فایل CSS مربوطه نمایش وب ویو، layout مربوط به MainActivity و حتی strings که در آن نام برنامه و تعدادی متن دیگر را تغییر داده ام. در ضمن اگر قرار است کلاسی فقط در اینجا وجود داشته باشد همانطور که گفته شد آن را باتوجه به نیاز اضافه می کنیم و در داخل کد استفاده. خیلی راحت و خوش مزه!</p>
<p><span style="color: #99cc00;"><strong>حالا نوبت به نحوه استفاده از flavor ایجاد شده می رسد، قبلش یک نکته کوچک:</strong></span></p>
<p>همانطور که حتماً مستحضر هستید می توان حالات مختلفی برای  <strong>Build</strong> با  <strong>BuildTypes  </strong> داشته باشیم. می توان متغیر تعریف کرد، obfuscate کرد و یا تسک خاصی را به همراه <strong>Build</strong> اجرا کرد. بطور مثال تفاوت آدرس های  api در Release و debbug را می توان با <strong>BuildTypes</strong> هندل کرد. به مثال زیر توجه کنید:</p><pre class="crayon-plain-tag">buildTypes {
    release {
        minifyEnabled true
        proguardFiles 'proguard-base.txt', 'proguard-rules.pro'
        buildConfigField "String", "SERVER_ADDRESS", "\"http://api.neginserver.com:8989\""
        buildConfigField "String", "API_VERSION", "\"v1\""
        buildConfigField "String", "SKU_PREMIUM", "\"premium\""

        signingConfig signingConfigs.negin

    }

    debug_in_main_server {
        initWith(buildTypes.debug)
        buildConfigField "String", "SERVER_ADDRESS", "\"http://api.neginserver.com:8989\""
        buildConfigField "String", "API_VERSION", "\"v1\""
        buildConfigField "String", "SKU_PREMIUM", "\"premium_debug3\""

    }

    debug {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        buildConfigField "String", "SERVER_ADDRESS", "\"http://192.168.34.24:8989\""
        buildConfigField "String", "API_VERSION", "\"v1\""
        buildConfigField "String", "SKU_PREMIUM", "\"premium_debug3\""

    }
}</pre><p></p>
<p style="text-align: justify;">همانطور که ملاحظه می کنید در این سه نوع خروجی از برنامه سه تا متغیر تعریف شده که با توجه به انتخاب <strong>build</strong> خودش بطور خودکار انتخاب و در برنامه استفاده می شود. فقط کافیست درجایی از کد بصورت زیر استفاده کنید:</p>
<p></p><pre class="crayon-plain-tag">String serverAddress = BuildConfig.SERVER_ADDRESS;
String apiVersion = BuildConfig.API_VERSION;
String url_base_services = serverAddress + "/api/"+apiVersion;</pre><p></p>
<p style="text-align: justify;"><span style="color: #99cc00;"><strong>خیلی خوب، بر می گردم سر موضوع اصلی یعنی نحوه استفاده از flavor</strong></span></p>
<p style="text-align: justify;">برای استفاده از flavor باید به منوی Build Varians در Android Studio رفته و بعد از انتخاب گزینه مورد نظر برنامه را لانچ یا build بگیریم. نکته جالب این است که می توان با ترکیب BuildConfig و Flavor حالات بسیار زیادی برای Build برنامه ایجاد کرد که واقعاً کاربردی و ضروری است یعنی به تعداد BuildType در تعداد flavor ، حالت Build خواهیم داشت ( همانطور که می بینید  ۴  = (debug | release )ضرب(freeVersion | primary) حالت داریم.) و به راحتی می توانیم درهرلحظه Build مورد نظر را با حداقل تغییرات در کد( تغریباً صفر!) انجام دهیم.</p>
<p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2595" src="http://www.mahditajik.ir/wp-content/uploads/2017/09/flavor3-1.jpg" alt="" width="573" height="504" srcset="http://www.mahditajik.ir/wp-content/uploads/2017/09/flavor3-1.jpg 573w, http://www.mahditajik.ir/wp-content/uploads/2017/09/flavor3-1-300x264.jpg 300w" sizes="(max-width: 573px) 100vw, 573px" /></p>
<p>امیدوارم این آموزش براتون مفید بوده باشه. سوالات و نقطه نظرات خود را با من به اشتراک بگذارید.</p>
<p>منبع: <a href="http://www.biitecode.ir" target="_blank" rel="noopener">بایت کد</a></p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/gradle-product-flavors/">مزایا و نحوه استفاده از Product Flavors در Gradle</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.mahditajik.ir/gradle-product-flavors/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<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>
<p></p><pre class="crayon-plain-tag">compile 'com.google.dagger:dagger:2.7'
annotationProcessor 'com.google.dagger:dagger-compiler:2.7'</pre><p></p>
<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>
<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>
<p><pre class="crayon-plain-tag">@Qualifier</pre></p>
<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>
<p></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><p><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>
<p></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><p><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>
<p></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></p>
<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>
<p></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><p><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>
<p></p><pre class="crayon-plain-tag">@Component(dependencies = ApplicationComponent.class, modules = ServiceModule.class)</pre><p></p>
<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>
<p></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></p>
<p style="text-align: justify;">و برای استفاده wire-up کردن هم متد ماژول ان را از کامپوننت اصلی بگیریم. ( خط ۲۷)</p>
<p></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></p>
<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>
<p></p><pre class="crayon-plain-tag">@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ScopeName{
}</pre><p>منبع: <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>کار با CollapsingToolBar به همراه مثالی ساده</title>
		<link>http://www.mahditajik.ir/how-to-use-collapsingtoolbar/</link>
					<comments>http://www.mahditajik.ir/how-to-use-collapsingtoolbar/#respond</comments>
		
		<dc:creator><![CDATA[mahdi]]></dc:creator>
		<pubDate>Wed, 26 Apr 2017 16:44:26 +0000</pubDate>
				<category><![CDATA[آموزش]]></category>
		<category><![CDATA[material-design]]></category>
		<category><![CDATA[UI]]></category>
		<guid isPermaLink="false">http://www.mahditajik.ir/?p=2254</guid>

					<description><![CDATA[<p>کار با CollapsingToolBar به همراه مثالی ساده حتماً شما هم افکت های زیبای Material Design را دیده اید که چگونه با اسکرول دادن لیست، toolBar و عناصر دیگر با یک افکت زیبا جمع شده و به بالا می روند. چی؟! راجع بهش می دونید و ازش استفاده می کنید؟ باشه من می خوام در این ...</p>
<p>نوشته <a rel="nofollow" href="http://www.mahditajik.ir/how-to-use-collapsingtoolbar/">کار با CollapsingToolBar به همراه مثالی ساده</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></description>
										<content:encoded><![CDATA[<p><strong>کار با CollapsingToolBar به همراه مثالی ساده</strong></p>
<p>حتماً شما هم افکت های زیبای <strong>Material Design</strong> را دیده اید که چگونه با اسکرول دادن لیست، <strong>toolBar</strong> و عناصر دیگر با یک افکت زیبا جمع شده و به بالا می روند. چی؟! راجع بهش می دونید و ازش استفاده می کنید؟ باشه من می خوام در این مقاله  نحوه صحیح پیاده سازی <strong>CollapsingToolBar</strong>  را  باهم برسی کرده و ابهامات احتمالی موجود در گوشه ذهنمون رو بر طرف کنم. پس چه دوستانی که با این کتابخانه آشنا هستند و چه شمایی که تازه می خواهید شروع کنید، تا آخر این مقاله با من باشید. پیشنهاد من اینکه یکبار مقاله را کامل بخوانید و بعد بروید سراغ کد. ۹۰ درصد سوالات برطرف می شود و اگر دوباره مقاله را بخوانید ۱۰ درصد بقیه نیز اوکی میشود. انشاء الله <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>&nbsp;</p>
<p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2261" src="http://www.mahditajik.ir/wp-content/uploads/2017/04/video_2017-04-26_17-02-07.gif" alt="" width="360" height="640" /></p>
<p><strong>تعریف:</strong></p>
<p><strong>CollapsingToolBar</strong> یک <strong>wrapper</strong> یا غلاف برای <strong>ToolBar</strong> هست که خودش مشتق شده از <strong>AppBar</strong> است و طراحی شده تا فرزند <strong>AppBarLayout</strong> باشد. خود <strong>AppBarLayout</strong> یک <strong>LinearLayout</strong> است با این امکان که اکثر افکت ها و امکانات <strong>Material Design</strong>  در فرزند های آن قابل استفاده است و اجازه می دهد تا <strong>ToolBar</strong> و <strong>View</strong> های دیگر نسبت اسکرول شدن View های وابسته (<strong>NestedScrollView</strong> و یا <strong>RecyclerView</strong>) عکس العمل نشان بدهند و افکت های Material Design را اعمال کنند.حتماً می دانید که AppBarLayout باید والد یا parent آن <strong>CoordinatorLayout</strong> باشد. خود <strong>CoordinatoLayout</strong> نیز <strong>Super FrameLayout</strong> است که معمولا به عنوان والد اصلی لیوت ها بکار گرفته می شود. برای جلو گیری از پیچیده شدن مطلب به نمودار زیر توجه کنید:</p>
<p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2259" src="http://www.mahditajik.ir/wp-content/uploads/2017/04/coordinatorlayout.jpg" alt="" width="500" height="800" srcset="http://www.mahditajik.ir/wp-content/uploads/2017/04/coordinatorlayout.jpg 500w, http://www.mahditajik.ir/wp-content/uploads/2017/04/coordinatorlayout-188x300.jpg 188w" sizes="(max-width: 500px) 100vw, 500px" /></p>
<p>خیلی خوب بیاید یکبار بالعکس دفعه قبل از بالا به پایین برسی کنیم:</p>
<p><strong>CoordinatorLayout</strong> لازم است تا بتوانیم <strong>AppBarLayout</strong> داشته باشیم. <strong>AppBarLayout</strong> هم باید باشد تا بتوانیم <strong>CollapsingToolBarLayout</strong> داشته باشیم. درون <strong>CollapsingToolBarLayout</strong> هم یک <strong>ToolBar</strong> برای برنامه می گذاریم و یک <strong>ImageView</strong>. ما می خواهیم با اسکرول خوردن لایه محتوا، کل <strong>CollapsingToolBarLayout</strong> و کامپوننت های داخل آن به جز <strong>ToolBar</strong>جمع شود. در هر کدام از این کامپوننت ها هم باید <strong>Property</strong> های مخصوص را به درستی مقدار دهی کنیم. اول اینکه در <strong>CollapsingToolBarLayout</strong> باید فلگ اسکرول را بدهیم که مشخص می کند نسبت به اسکرول لایه محتوا چه عکس العملی نشان دهد. در ضمن می توان برای <strong>ToolBar</strong> یا کامپوننت های داخل <strong>CollapsingToolBarLayout</strong> نوع جمع شدن ان را مشخص کرد که می تواند بصورت <strong>Paralex</strong> یا <strong>pin</strong> باشد. استفاده از <strong>paralex</strong> برای <strong>ImageView</strong> بسیار جالب خواهد بود و با سرعتی کمتر از سرعت اسکرول از صفحه خارج خواهد شد. ( سایت های <strong>paralex</strong> رو حتماً دیده اید!) البته گزینه <strong>pin</strong> فقط روی <strong>ToolBar</strong> کار می کند و توسط آن بعد از جمع شدن کل <strong>CollapsingToolBarLayout</strong> فقط <strong>ToolBar</strong> بالای صفحه باقی می ماند و به اصطلاح <strong>Pin</strong> می شود. البته توجه کنید که نمی توان <strong>Pin</strong> را مثلا روی <strong>ImageView</strong> اعمال کرد.</p>
<p>بسیار خوب، از طرفی هم به لایه محتوی باید بگوییم که قرار است تغییرات اسکرولش به <strong>AppBarLayout</strong> اطلاع داده شود که این امر با ست کردن <strong> layout_behavior</strong> محقق می شود.</p>
<p>همه اینها در تصویر پایین رسم کرده ام تا بسیار راحت جمع بندی کنیم.</p>
<p><img decoding="async" loading="lazy" class="aligncenter size-full wp-image-2269" src="http://www.mahditajik.ir/wp-content/uploads/2017/04/coordinatorlayout2-1.jpg" alt="" width="1300" height="800" srcset="http://www.mahditajik.ir/wp-content/uploads/2017/04/coordinatorlayout2-1.jpg 1300w, http://www.mahditajik.ir/wp-content/uploads/2017/04/coordinatorlayout2-1-300x185.jpg 300w, http://www.mahditajik.ir/wp-content/uploads/2017/04/coordinatorlayout2-1-768x473.jpg 768w, http://www.mahditajik.ir/wp-content/uploads/2017/04/coordinatorlayout2-1-1024x630.jpg 1024w" sizes="(max-width: 1300px) 100vw, 1300px" /></p>
<p>حالا می تونید برگردید و تعریف رو دوباره بخونید. خیلی خوب! ببینیم چطور می تونیم این افکت ها را ایجاد و مدیریت کنیم. استفاده از <strong>Component</strong> های یاد شده به همراه چند <strong>Scroll_flags</strong> باعث ایجاد افکت های <strong>Scrolll</strong> می شود که بصورت زیر است:</p>
<p><strong>Scroll</strong><br />
اگر از فلگ<br />
<pre class="crayon-plain-tag">scroll</pre><br />
استفاده نکنیم اصلا ToolBar اسکرول نخواهد خورد و از این فلگ را معمولا با ترکیب فلگ های دیگر استفاده می کنیم.</p>
<p><strong>enterAlways</strong><br />
با استفاده از فلگ<br />
<pre class="crayon-plain-tag">enterAlways</pre><br />
بعد از اینکه آیتم از صفحه خارج شد با اولین اسکرول برعکس بعدی دوباره نمایان می شود. اگر از فلگ<br />
<pre class="crayon-plain-tag">scroll</pre><br />
به تنهایی استفاده کرده بودیم باید تمامی صفحات اسکرول شده را برگردیم تا دوباره آیتم خارج شده (ToolBar یا هر آیتمی که این فلگ به او نسبت داده شده) به صفحه باز گردد. موارد را در مثال می توانید مشاهده کنید و حتی با دانلود کل کد از gitHub تک تک آنها را خودتان امتحان نمایید. پس نگران نباشید!</p>
<p><strong>exitUntilCollapsed</strong><br />
با استفاده از این فلگ، لیست بصورتی عمل می کند که با اسکرول لیست به سمت بالا کم کم فضای آیتم را گرفته و آیتم از بالا به بیرون می رود و باید همه صفحه های اسکرول شده در<br />
<pre class="crayon-plain-tag">exitUntilCollapsed</pre><br />
بصورت عکس اسکرول شوند تا آیتم (ToolBar یا هر آیتمی که این فلگ به او نسبت داده شده) دوباره باز گردد. فقط حواسمان باشد که این فلگ برای CollapsingToolBar عمل می کند و برای آیتم های دیگر کارایی ندارد!</p>
<p>کد نمودار بالا بصورت زیر است:</p><pre class="crayon-plain-tag">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"&gt;
    &lt;!-- fitsSystemWindows: hen enabled, the AppBarLayout assumes that the status bar is not available and it has to occupy the entire real estate. --&gt;

    &lt;android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="256dp"
        android:theme="@style/AppTheme.AppBarOverlay"&gt;

        &lt;android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsingToolBar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:contentScrim="@color/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"&gt;
            &lt;!-- * contentScrim: when collapsing the toolbar color change to this, if you want to use this feature do not set background color for toolBar --&gt;

            &lt;ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax"
                android:src="@drawable/ic_back"/&gt;

            &lt;android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:elevation="7dp"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_collapseMode="pin"/&gt;

            &lt;!-- * layout_collapseMode: indicate how our tool bar act to collapsing pin on top or paralex --&gt;

        &lt;/android.support.design.widget.CollapsingToolbarLayout&gt;


    &lt;/android.support.design.widget.AppBarLayout&gt;

    &lt;include layout="@layout/content_main"/&gt;

    &lt;android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        app:layout_anchor="@id/app_bar"
        app:layout_anchorGravity="bottom|right"
        app:srcCompat="@android:drawable/ic_dialog_email"/&gt;
    &lt;!-- * layout_anchorGravity: layout_gravity should removed so the layout_anchorGravity works --&gt;
    
&lt;/android.support.design.widget.CoordinatorLayout&gt;</pre><p><strong>نکته۱:</strong><br />
گزینه<br />
<pre class="crayon-plain-tag">contentScrim</pre><br />
در<br />
<pre class="crayon-plain-tag">CollapsingToolbarLayout</pre><br />
باعث می شه که بعد از جمع شدن بجای استفاده از بخش مانده از تصویر به عنوان بک گراند، رنگش به رنگ مورد نظر ما تغییر بکنه. حواستون باشه این گزینه وقتی کار میکنه که شما<br />
<pre class="crayon-plain-tag">toolBar</pre><br />
رنگ پس زمینه نگذاشته باشین.</p>
<p><strong>نکته۲:</strong><br />
گزینه<br />
<pre class="crayon-plain-tag">layout_anchor</pre><br />
باعث میشه که کامپوننت های درون<br />
<pre class="crayon-plain-tag">CoordinatorLayout</pre><br />
بتونند به آیتم های دیگه اصطلاحاً لنگر بندازن و بهشون وصل بشوند و اتفاقات مربوط به اسکرول روی انها نیز تاثیر بگذارد. همانطور که در کد می بینید ما<br />
<pre class="crayon-plain-tag">floatingActionButton</pre><br />
را به<br />
<pre class="crayon-plain-tag">appBarLayout</pre><br />
وصل کردیم و توسط گزینه<br />
<pre class="crayon-plain-tag">layout_anchorGravity</pre><br />
موقعیت آن را نیز مشخص کردیم. اگر این مشخصه نبود ما باید احتمالا یک انیمیتی دستی به<br />
<pre class="crayon-plain-tag">floatingActionButton</pre><br />
می دادیم تازه اونم سینک کردنش با انیمیت اسکرول داستانی برای خودش. پس به راحتی می تونیم این طوری هندلش کنیم.</p>
<p>همانطور که می بینید با استفاده از کامپوننت های <strong>CollapsingToolBar </strong> و <strong>AppBarLayout</strong> و <strong>CoordinatorLayout</strong> با دادن چند Property ساده تونستیم افکت زیبای <strong>Material Design</strong> را داشته باشیم. امیدوارم این مقاله براتون مفید بوده باشه.</p>
<p>کد کامل رو از اینجا بگیرید و خودتان تست کنید.</p>
<p><a href="https://github.com/mahdit83/CollapsingToolBarDemo/tree/master" 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/how-to-use-collapsingtoolbar/">کار با CollapsingToolBar به همراه مثالی ساده</a> اولین بار در <a rel="nofollow" href="http://www.mahditajik.ir">Mahdi Tajik</a> پدیدار شد.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.mahditajik.ir/how-to-use-collapsingtoolbar/feed/</wfw:commentRss>
			<slash:comments>0</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>
<p><pre class="crayon-plain-tag">Provides@</pre></p>
<p style="text-align: justify;">نحوه تولید وابستگی ها را مشخص می کند. هر جا که این انوتیشن بروی متدی بود یعنی خروجی این متد قرار است در جایی از برنامه تزریق شده و مورد استفاده قرار گیرد.</p>
<p><pre class="crayon-plain-tag">Module@</pre></p>
<p style="text-align: justify;">کلاسی هست که <strong>Provider</strong> ها در آن قرار می گیرند.</p>
<p><pre class="crayon-plain-tag">Component@</pre></p>
<p style="text-align: justify;">اینترفیسی که ارتباط وابستگی ها و استفاده کننده آن را مطرح می کند. ما فقط اینترفیس را می نویسیم و پیاده سازی آن با خود <strong>Dagger</strong> است.</p>
<p><pre class="crayon-plain-tag">Inject@</pre></p>
<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>
<p></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><p></p><pre class="crayon-plain-tag">public class Radiator {
    private String name;

    public Radiator(String name){
        this.name = name;
    }
}</pre><p></p>
<p style="text-align: justify;">همانطور که دیدیم دو کلاس رادیاتور و کامپیوتر را داریم که وابستگی خاصی ندارند. حال نوبت به تعریف کلاس موتور می رسد. برای ایجاد و بیان وابستگی از انوتیشن <strong>Inject@ </strong>استفاده می کنیم و <strong>Dagger</strong> می فهمد که باید یک وابستگی را تزریق کند.</p>
<p></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></p>
<p style="text-align: justify;">پس ما تا اینجا نحوه وابستگی کلاس ها را با انوتیشن <strong>Inject@ </strong>مشخص کردیم. یعنی به <strong>Dagger</strong> گفتیم که هنگام ساخت موتور رادیاتور و کامپیوتر را در اختیارم قرار بده! ( حالا نمی دانم چطوری، هرطور خودت صلاح می دونی!) ولی قبل آن لازم است تا یکبار نحوه ساخته شدن وابستگی ها را به <strong>Dagger</strong> را معرفی کنیم. برای اینکار کلاسی با نام ماژول می سازیم که از انوتیشن <strong>Module@ </strong>استفاده می کند و بخش های آن که نحوه ساختن وابستگی را شرح می دهند با انوتیشن <strong>Provides@ </strong>مشخص می کنیم.</p>
<p></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></p>
<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>
<p></p><pre class="crayon-plain-tag">@Singleton
@Component(modules = {MotorModule.class})
public interface MotorComponent {

    void inject(MainActivity activty);
    void inject(Motor moto);

}</pre><p></p>
<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>
<p></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></p>
<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>
<p></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></p>
<p style="text-align: justify;">پس <strong>Dagger</strong> می فهمد که برای ساخت موتور باید دو ورودی رادیاتور و کامپیوتر به موتور پاس دهد، از طرفی نحوه ساخت کامپیوتر و رادیاتور را می داند. پس همین کافی است که بتواند موتور را برایمان تولید کند و <strong>Component</strong> هم بصورت زیر می شود:</p>
<p></p><pre class="crayon-plain-tag">@Singleton
@Component(modules = {MotorModule.class})
public interface MotorComponent {

    void inject(MainActivity activty);

}</pre><p></p>
<p style="text-align: justify;">حال اگر از شما بپرسند چرا متدی قرار دادیم با نام <strong>inject</strong> که ورودی آن از جنس <strong>MainActivity</strong> است جواب دهید: بخاطر اینکه در <strong>MainActivity </strong>در فیلد <strong>Motor </strong>را تزریق کرده ایم! بله درست گفتید!</p>
<p></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></p>
<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>
