خیلی وقت بود که دوست داشتم روی اپ‌های ماژولار کار کنم، این دوست داشتن مقدمه‌ی یه هفته‌ای مطالعه و تست بود که در نهایت خروجیش تبدیل به ریپوی AndroidModularization توی گیت‌هاب شد. در کنار هدف اصلی (اپ ماژولار) یه هدف فرعی هم داشتم که یه نمونه کد authentication با قابلیت رفرش شدن توکن برای وب‌سرویس moviesapi.ir درست کنم. اگر بخوام خلاصش کنم میشه این پروژه یه اپ ماژولار هست که از قابلیت‌های وب‌سرویس moviesapi.ir استفاده میکنه.

توی توسعه این پروژه از کتابخونه‌هایی مثل Rxjava ,Dagger2 ,Retrofit, Room , Databinding و … استفاده شده ولی تمرکز اصلی روی ساخت اپ ماژولار با استفاده از Dagger2 بوده. یعنی اگر میخواید RxJava یاد بگیرید، توی این پروژه نباید دنبال Best Practiceهاش باشید.

 

چرا اپ ماژولار خوبه؟

مهمترین دلیلی که خیلی از افراد و شرکت‌ها به سمت اپ‌های ماژولار میرن، افزایش سرعت بیلد هست. توی پروژه‌های بزرگ این قضیه یه مشکل خیلی حاد میشه. مورد بعدی اینه که توسعه‌ی پروژه رو در آینده خیلی راحت‌تر میکنه، بطور مثال هر ماژول رو یه تیم میتونه جداگونه توسعه بده و ویژگی‌های جدید بهش اضافه کنه بدونه اینکه کاری به بقیه ماژول‌ها داشته باشه.

 

چالش‌های توسعه اپ ماژولار چیه؟

مهمترین چالش‌هایی که توی ساخت این پروژه بهش برخورد کردم این سه مورد بود:

۱- جا به جایی کاربر بین صفحاتی که در ماژول‌های متفاوت هستند (اکتیویتی به اکتیویتی یا فرگمنت به فرگمنت یا …)

۲- استفاده از Dagger2

۳- مدیریت نسخه‌ی کتابخونه‌هایی که به عنوان dependency استفاده میشن

 

ساختار پروژه بهمراه وابستگی‌ها در یک نگاه!

پروژه سه بخش اصلی داره:

۱- بخش Core: کلاس‌هایی که در کل اپ مشترک هستند. مثلا کلاس‌های Base، وب‌سرویس‌هایی که توی کل پروژه نیاز هست، کلاس‌های مرتبط با Navigation و … . البته درصورت نیاز میشه core رو تبدیل به ماژول‌های جداگونه کرد.

۲- بخش Features: بین Core و App قرار دارند. هر کدوم از featureها میتونند برای خودشون درخواست‌های وب‌سرویس جداگونه یا دیتابیس داشته باشند. برای نمونه توی این پروژه سه تا Feature داریم.

الف) authentication – داخلش صفحات ورود کاربر و ثبت‌نام هس

ب) main – داخلش صفحه‌ی نمایش لیست فیلم‌ها و جزییاتش هست

ج) search – داخلش صفحه‌ی جستجو هست که تاریخچه‌ی جستجو‌های قبلی رو نشون میده. این Feature برای خودش دیتابیس داخلی داره.

۳- بخش App: ماژولی هس که باعث میشه apk ساخته بشه. تنها ماژولی هست که به همه ماژول‌های دیگه وابستگی داره. توی اندروید حتما نیازه همچین ماژولی داشته باشیم که از نوع Application باشه.

 

حل کردن چالش‌ها!

چالش جا به جایی بین صفحات (Navigation)

اولین نکته‌ توی حل چالش Navigation اینه تصمیم بگیرید که آیا قراره Featureیی داشته باشید که فقط فرگمنت توش باشه یا نه؟ منظور اینه اگر همه Featureها حداقل یه اکتیویتی داشته باشند، نقطه‌ی ورود به هر ماژول (EntryPoint)  میتونه از اون طریق باشه. یعنی اگر کاربر از صفحه‌ای توی Main میخواد به Search بره، توی Search یه اکتیویتی باشه تا کاربر به اون بره.

مزایا و معایب این صورت هست:

مزایا: توسعه پروژه خیلی راحت‌تر میشه. برای ارتباط بین Featureها میشه یه کلاس Naivgation درست کرد که با استفاده از deeplink بدونه وابستگی به ماژول خاصی کار انتقال کاربر بین Featureهارو انجام بده. همه Featureها به کلاس Naivgation وابسته هستند و خود Navigation به جایی وابسته نیست. در نتیجه درگیر circular dependency نمیشم.

معایب: مجبورید برای هر Feature یه اکتیویتی درست کنید که خیلی اصلا نیاز نیست.

همونجور که گفتم پیاده‌سازیش راحته مثل زیر میشه:

کد کلاس Navigation هم این مدلی میشه.

چون uri استفاده میشه نیاز به این نیست navigation برای انتقال کاربر به اکتیویتی داخل Main به اون وابسته باشه. خود اندروید اکیتیویتی مناسب رو پیدا میکنه.

حالا اگر دوست داشته باشید Featureیی داشته باشید که فقط داخلش فرگمنت باشه قضیه پیچیده‌تر میشه. همشم زیر سر circular dependencyهست!! توی این حالت کد Navigation این شکلی میشه:

این کد باعث میشه یه وابستگی بین navigation با ماژول اون فرگمنت پیش میاد که باعث circular dependency میشه.

با درست کردن یه interface که Search داخلش مشخص میکنه که بقیه ماژول‌ها چطوری میتونن باهاش ارتباط داشته باشن (درواقع EntryPointهاشو تعیین میکنه) این circular dependency حل میشه.

البته پیاده سازیش به این تمیزی نیست. اگر برید توی کد ببینید متوجه میشید چی میگم D: چون تنهایی جایی که میشده این کلاس‌هارو new کنم و توی ماژول‌های مختلف بهش دسترسی داشته باشم بدونه اینکه وابستگی مستقیم درست کنم، کلاس application بوده. یه اینترفیس EntryPointHolder دارم که کلاس application اونو پیاده میکنه، در نتیجه چون همه ماژول‌ها به application context دسترسی دارن میتوننن آبجکت‌های EntryPoint رو بگیرن.

غیر از circular dependency یه مشکل دیگم هست. فرض کنید یه اکتیویتی توی ماژول A داریم که داخل خودش یه فرگمنت از همون ماژول A نشون میده (شکل شماره ۱). کاربر روی دکمه میزنه و فرگمنت ۱ از ماژول B توی اکتیویتی ماژول A نشون داده میشه (شکل شماره ۲). حالا بدونه اینکه فرگمنت ۱ از ماژول B خبر داشته باشه (چون کلا نمیدونه توی کجا داره نمایش داده میشه) ما میخوایم از فرگمنت ۱ به فرگمنت ۲ همون ماژول B بریم! (شکل شماره ۳)

برای اینکار از همون ایده که توی SingleAcitivityPattern استفاده کردم، کمک گرفتم. یعنی هر Acitvity و Fragmentیی که داخل خودش میخواد یه سری فرگمنت رو مدیریت کنه باید اینترفیس HasNavigator رو پیاده سازی کنه. بعدا اگر جایی شبیه همین مثالی که گفتم گیر کردیم، فرگمنت ۱ ماژول B با استفاده از کلاس NavigationManager به نزدیک‌ترین navigator که مسئول مدیریتش بوده (اینجا میشه naivgatorیی که توی Acitivity ماژول A هست) دسترسی پیدا میکنه. بعد به اون میگه الان باید فرگمنت ۲ از ماژول B نشون داده بشه. کد کلاس navigationManager رو ببینید متوجه میشید که این قضیه سلسله مراتبی چطوری هندل شده.

شکل شماره ۱

شکل شماره ۲

شکل شماره ۳

چالش Dagger2

مدلی که از dagger2 توی این پروژه استفاده کردم، این شکلی هست که یه application component داریم که توی ماژول core با اسکوپ singleton هست. ماژول‌های Feature هم چون به core وابستگی دارن میتونن ازش استفاده کنند. اول میخواستم هر ماژول subcomponent اون application component بشه! اما باز مشکل circular dependency پیش اومد. چون subcomponent توی dagger2 اینجوریه که application component باید یه وابستگی با subcomponentش داشته باشه که توی این پروژه چون هرکدوم ماژول مختلف هستند، این circular dependency پیش میاد. واسه همین بین کامپوننتهای هر Feature با application component از component dependency استفاده کردم. ولی اگر مثلا توی خود Feautre یه اکتیویتی بود که یه سری فرگمنت داشت، رابطشون رو همون subcomponentیی درست کردم.

 

چالش مدیریت نسخه‌ی کتابخونه‌ها

از یه روش ساده استفاده کردم (راه حل بهترش استفاده از kotlin+buildsrc هست) یه فایل گریدل به اسم libraries.gradle ساختم و همه کتابخونه‌هایی که نیاز دارمو اونجا نوشتم. بعد ماژول‌ها اگر میخوان کتابخونه‌ی رو به عنوان dependency استفاده کنند، بجای اینکه خودشون مستقیم نسخه و اسم کتابخونه رو بنویسه از libraries.gradle استفاده میکنه.

 

نتیجه نهایی

پروژه‌ای که با این روش ساختم رو روی توی گیت‌هاب گذاشتم، از طریق لینک زیر میتونید بهش دسترسی داشته باشید. قرار هست از این کد با کمی تغییر به عنوان پایه‌ی پروژه‌ای استفاده کنم، حتما در آینده سعی میکنم در مورد اینکه چقدر بهم کمک کرده یا معایبی داشته یه مقاله بنویسم. اگرم کسی پیشنهاد یا سوالی داره، ممنون میشم بهم بگه تا در موردش بیشتر بحث کنیم.

لینک ریپوی گیت‌هاب

روزی که جنریتور “حلما” رو درست کردم، تصمیم گرفتم Open Sourceش کنم. چون اولین بار بود که میخواستم اینکارو بکنم، هیچ ایده‌ای نداشتم که از کجا باید شروع کرد یا باید به چه نکاتی توجه کنم. به همین دلیل، پیش یکی از بهترین دوستام به اسم گوگل!! رفتم تا مثل همیشه کمکم کنه، توی گوگل با کلیدواژه‌های start، open source و how جستجو کردم. بیشتر مقاله‌هایی که آورد رو خوندم، یه تعدادیشون نکته‌های خیلی خوب داشتند، این نکته‌هارو توی Evernote نوشتم تا سرفرصت تبدیلشون کنم به این مقاله‌ای که الان میخونید. نکته‌هارو به دو گروه زیر تقسیم کردم:

گروه اول- نکاتی که قبل از Open Source کردن یه پروژه باید بهشون توجه کرد.

گروه دوم- نکاتی که وقتی یه پروژه Open Source شد باید بهشون توجه کرد.

 

اگر شمام پروژه‌ای درست کردید که میخواید Open Sourceش کنید یا تصمیم دارید در آینده اینکارو انجام بدید، بنظرم خوندن این مقاله میتونه بهتون کمک کنه. اولین نکته‌ای که باید بهش توجه کنید اینه که گذاشتن یه نمونه کد توی توی گیت‌هاب با داشتن پروژه Open Source متفاوته. یعنی اگر کسی یه نمونه کد رو روی گیت‌هاب بذاره، نمیتونه بگه من یه پروژه Open Source دارم! درواقع اون یه نمونه کد داشته که رایگان در اختیار بقیه برنامه‌نویس‌ها گذاشته. اگر میخواید یه پروژه Open Source داشته باشید بهتر به این سه مورد توجه کنید، اول اینکه پروژه‌‌ای بسازید که مفید باشه، دوم توسعه‌اش رو ادامه بدید و اینجوری نباشه بعد یکی دو هفته بیخیال پروژه بشید، سوم مشارکت بقیه برنامه‌نویس‌هارو توی پروژه‌اش قبول کنید.

 

گروه اول- نکات قبل از Open Source کردن

معرفی پروژه

قبل اینکه پروژه رو Open Source کنید، به صورت خلاصه توی یه پاراگراف بنویسید قراره چه مشکلی رو حل کنه و برای استفاده چه چیزهایی نیاز داره. حواستون باشه این پاراگراف رو کسایی میخونند که هیچ شناختی از پروژتون ندارند. بعد همیشه این پاراگراف رو یه جای دم دست نگه دارید، چون احتمالا توی جاهای زیادی (تو چت،شبکه‌های اجتماعی،فروم‌ها و …) باید در مورد پروژه صحبت کنید و میتونید همین پاراگراف رو سریع براشون بفرستید.

 

انتظار مشارکت زیاد از بقیه برنامه‌نویس‌ها

این فکر اشتباه رو نداشته باشید که وقتی پروژه Open Source بشه، یهو بقیه برنامه‌نویس‌ها میان کمکتون و همه‌ی کارهارو میکنند! بیشتر پروژه‌های Open Source رو اگر بررسی کنید، درصد زیادی از کد پروژه توسط گروه کوچکی از برنامه‌نویس‌ها نوشته شده که بصورت خاص رو اون پروژه کار می‌کنند (مثلا توی شرکتی هستند که پروژه برای اونجاس یا پول می‌گیرند). خیلی از پروژه‌ها هم نمی‌تونند بیشتر از بنیان‌گذارهاش برنامه‌نویس‌های دیگه‌ای جذب کنند و بعد یک سال متوقف می‌شند. بهتره همون اول پروژه سعی کنید از طریق صحبت کردن توی فروم‌ها یا نوشتن پست بلاگ تعدادی برنامه‌نویس برای مشارکت توی پروژه پیدا کنید. خوبیش اینه چون از شروع پروژه کنارتون هستند، حس میکنند این پروژه برای خودشونه و تلاش بیشتری می‌کنند.

 

مزایای Open Source کردن پروژه

از مزایای Open Source کردن پروژه میشه به موارد زیر اشاره کرد:

۱- باعث آزادی بیشتر میشه. مثلا روی پروژه‌ای کار می‌کنید که صاحبش شرکت هست، Open Source شدنش باعث میشه که در آینده حتی اگر از اون شرکت هم بیرون اومدید، بتونید روش کار کنید.

۲- حس مفید بودن می‌کنید و احساس بهتری پیدا می‌کنید.

۳- با تاثیری که پروژتون رو دنیای برنامه‌نویس‌ها میذاره، برای همیشه یه اثر و ردپا از شما می‌مونه.

۴- راحت‌تر میشه به مشکلاتی که توی پروژه دارید لینک بدید و از بقیه کمک بگیرید. کسی هم که میخواد کمک کنه چون به سورس دسترسی کامل داره، خیلی بهتر کمکتون میکنه.

 

معایب Open Source کردن پروژه

Open Source شدن پروژه در کنار مزایا بالا، معایبی هم داره. مثل:

۱- هرچی از شروع پروژه میگذره کار سخت‌تر میشه! وظیفه‌هاتون خیلی زیاد میشه مثل توسعه‌ی دادن کد، نوشتن داکیومنت، جواب دادن به سوال کسایی که از پروژه استفاده می‌کنند ،بررسی کدهایی که بقیه برای مشارکت توی توسعه پروژه فرستادن و بررسی درخواست ویژگی‌های جدید که براتون ارسال شده.

اگر فقط میخواید وظیفه‌ی توسعه دادن کد رو انجام بدید، بهتره به جای اینکه خودتون پروژه Open Source داشته باشید، به یکی از پروژه‌های موجود کمک کنید.

۲- موقع Open Source کردن در نظر داشته باشید که احتمالا این کار باعث میشه کسب درآمدتون سخت‌تر بشه. البته گاهی میشه به جای Open Source کردن کل پروژه‌ای که می‌فروشید و منبع درآمدتون هست، شبیه شرکت Dropbox، کتابخونه‌هایی که برای ساخت پروژه‌ی خودتون درست کردید رو Open Source کنید. اینجوری هنوز میتونید به فروش پروژه‌تون ادامه بدید.
البته توی بعضی موارد مجبورید پروژتون رو Open Source کنید و راه دیگه‌ای ندارید. بطور مثال اگر یه نرم افزار زیرساختی درست کردید(مثل سیستم‌عامل،دیتابیس و …)، انتخاب دیگه‌ای ندارید. هم-بنیانگذار Cloudera گفته که توی ده سال گذشته هیچ نرم افزار زیرساختی با Closed Sourceیی نبوده که بتونه خیلی معروف بشه و عده‌ی زیادی ازش استفاده کنند! توی اینجور پروژها، کاربرها معمولا از استک‌های Open Source استفاده می‌کنند.

۳- برعکس اینکه همه فکرمی‌کنند Open Source کردن باعث میشه هزینه‌ها کم بشه! نه تنها کم نمیشه، تازه زیادم میشه. چون در حالت معمول که کار می‌کنید، کسی اون کد رو نمی‌بینه و فقط کدتون کار کنه! کافیه. اما وقتی کدهارو بقیه می‌بینند مجبورید برای اینکه خجالت زده نشید، کلی وقت براشون بذارید!! همچنین غیر از کد زدن هم وظیفه‌های دیگه‌‌ای مثل داکیومنت نوشتن و … که قبلا بهشون اشاره کردم به کارهاتون اضافه میشند.

 

گروه دوم- نکات بعد از Open Source کردن

جذب مشارکت‌کننده

برای جذب مشارکت کننده میتونید در ازای اینکه کسی توی توسعه پروژه مشارکت کنه، بهش برنامه‌نویسی یاد بدید. شاید اوایل نتونند خیلی بهتون کمک کنند ولی در آینده تعدادی مشارکت کننده دارید که پیوسته روی توسعه پروژه باهاتون همکاری می‌کنند.

بجای اینکه توییتر خیلی کلی توییت کنید که بقیه بیان توی پروژه‌تون مشارکت کنند، به یه شخص خاص بگید، تاثیرش خیلی بیشتره. در ضمن سعی کنید توی قبول کردن پول ریکوئست‌ها خیلی دست و دل باز باشید، این کار باعث ایجاد انگیزه میشه و افراد بیشتری کمکتون کنند.

 

تبلیغ پروژه

معمولا برنامه‌نویس‌ها از اون مدل آدم‌هایی نیستند که خودشون رو تبلیغ کنند ولی توی این مورد باید بکنند! برای شروع میتونید یه پست بلاگ بنویسید یا داخل StackOverflow توی موضوعاتی که به پروژتون ربط داره سوال جواب بدید.

تو بحث‌های برنامه نویسی داخل Hakernews یا Reddit شرکت کنید (اگر بین ایرانی‌ها میخواید تبلیغ کنید، توییتر و تلگرام هست)

با پروژه‌های Open Source دیگه همکاری کنید! شاید پروژه‌تون بتونه بخشی از نیاز اون‌هارو رفع کنه و به عنوان dependency از پروژتون برای خودشون استفاده کنند! این اتفاق پروژه‌تون رو خیلی معروف‌تر میکنه.

 

انتخاب لایسنس

یکی از موضوعاتی که روی پروژه خیلی تاثیر داره اینه که چه لایسنی انتخاب میکنید، مثلا GPL سخت‌گیرانه رو انتخاب می‌کنید یا لایسنس های آسون‌تر مثل MIT


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

لیست تغییرات جدید
حتما لیست تغییرات داشته باشید و حداقل سه قسمت داشته باشه:‍

۱- نسخه‌ی جدید چه ناسازگاری‌هایی با نسخه‌ی قبلی داره

۲- چه ویژگی‌های جدید به سیستم اضافه شده

۳- چه باگ‌هایی در سیستم درست شدند.

حواستون باشه که قرار نیست توی لیست تغییرات یه سری پیام کامیت رو پشت هم بذارید! سعی کنید یه متن واضح و خوب بنویسید

نسخه‌گذاری
حتما از همون نسخه‌ی اولیه، نسخه‌گذاری رو انجام بدید، خیلی مهم نیس عدد نسخه رو چطور بالا میبرید، از الگویی پیرویی میکنید یا نه! فقط یادتون باشه نسخه گذاری کنید که کاربرهایی که از پروژه استفاده می‌کنند بتونند بفهمند چند نسخه با نسخه‌ی آخر فاصله دارند یا اگر باگ ریپورت میکنند بتونند نسخه‌ای که استفاده میکنند رو بگن.

راه ارتباطی با کاربرها و مشارکت‌کننده‌ها
توی Gitter کانال درست کنید تا بیشتر با کاربرها در ارتباط باشید، سعی کنید حتما سوال‌هایی که پرسیده میشه رو سریع جواب بدید، اینجوری کاربرا و مشارکت‌کننده‌ها میفهمن که برای اونها و پروژه‌ی خودتون اهمیت قائل هستید.
خیلی بده اگر در نظر نگیریدشون و بهشون اهمیت ندید!

ساخت وبسایت
حتما یه وبسایت برای پروژه درست کنید، یه سایت تک صفحه ای هم خیلی کمک میکنه. میتونید از Github Pages استفاده کنید.

ساخت Readme
فایل readme مناسب برای پروژه درست کنید. میتونید داخلش این موارد رو بنویسید:

۱- پاراگرافی که بصورت خلاصه در مورد پروژتون نوشتید رو داخل بذارید.
۲- توضیح بدید که چطور میشه پروژه رو اجرا کرد.
۳- آدرس وبسایت پروژه رو بذارید
۴- اسم و ایمیل کسایی که توی پروژه همکاری میکنند رو بنویسید

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

ساخت داکیومنت برای کاربران

کار خیلی سختیه ولی به همون اندازه مهمه! بدون راهنمایی کسی نمیتونه از پروژه استفاده!! لازم نیست همون اول کار یه راهنمای کامل بنویسی، یه داکیومنت ساده هم کافیه.
داکیومنت رو جزء ریپوزیتوری نذارید که بعد هر تغییر نیاز به پوش کردن باشه، داکیومنت باید جایی باشه که خیلی سریع و راحت بشه تغییرش داد.

نوشتن داکیومنت برای مشارکت کننده‌ها

‍۱- کدهای پروژه کجاس و چطوری میشه دریافت کردشون.

۲- در مورد فولدربندی پروژه یه توضیح مختصر بدید.

۳- اگر از build system استفاده میکنید، در مورد نحوه‌ی تنظیم کردنش توضیح بدید و بگید dependecyهای پروژه رو چطور باید گرفت.

۴- نحوه‌ی build کردن پروژه و اجرا کردن تست‌هارو توضیح بدید.

۵- شرایط مشارکت کردن توی پروژه رو بنویسید.

 

سخن پایانی که اعتماد به نفستون رو باید بالا نگه دارید،به مفید بودن کار خودتون اعتقاد داشته باشید. کدهاتون رو با کدهای بقیه مقایسه نکنید، پروژتون رو مقایسه نکنید، به خودتون گیر ندید که حتما باید از بقیه بهتر باشید!!!چون معیار این بهتر بودن مشخص نیست و امکانش نیست معیاری بشه براش تعریف کرد.

به اینکه بقیه دولوپرها شاید بعدا چیزهای بدید مورتون بگن رو نکنید ( مثلا بگن پروژتون بده،بی فایده‌اس و …)! توی اینترنت همیشه کسایی هستند که حتی اگر از آسمون هم پول بباره وجه منفیشو می‌بینند!!

منابع

http://blog.smartbear.com/open-source/how-to-turn-your-pile-of-code-into-an-open-source-project

http://www.wikihow.com/Have-a-Successful-Open-Source-Project

https://readwrite.com/2014/07/07/ open-source-software-pros-cons

https://opensource.com/life/15/5/4-steps-creating-thriving-open-source-project

https://www.smashingmagazine.com/2013/01/starting-an-open-source-project

هر موقع در مورد اینکه توی شرکت‌های خوب خارجی TDD کار میکنند صحبت میشد، پیش خودم میگفتم که خب توی ایران با توجه به ددلاین‌های پروژه، اخلاق کارفرما و … نمیشه مثل اونا بود وگرنه منم حتما TDD کار میکردم. برای خودم تست ننوشتن رو همینجوری توجیه میکردم تا اینکه تصمیم گرفتم یه پروژه که فرصت زیاد داشت رو بصورت TDD انجام بدم. همیشه فکرمیکردم Unit Testing خیلی راحته و اگر توی تست نوشتن بخوام جاییش گیر کنم قسمت Integration Testing و End to End Testing هست. ولی همون اول کار تا شروع به Unit Test نوشتن کردم، برام کلی سوال جورواجور پیش اومد! مثلا چطوری باید تست‌هارو نامگذاری کرد؟ چطوری میشه متدهایی که نیاز دارند با پارامترهای زیاد تست بشن رو تست کرد؟ حتما باید برای تست نوشتن از mockito استفاده کرد یا نه؟ ادامه …

میخواستم وقتی رسپبری‌پای خریدم، از کارهای جالبی که باهاش میکنم توی کانال و بلاگم بنویسم! ولی خب متاسفانه خیلی فرصت نمیشه سراغش برم، این تعطیلات چند روزه باعث شد تا بعد مدت‌ها سعی کنم کارهایی که میخواستم باهاش انجام بدم رو عملی کنم. مهمترین کارم این بود که بجای وصل کردن لپ‌تاپ به تلویزیون از رسپبری‌پای برای دیدن سریال یا ویدئوهای یوتیوب استفاده کنم. یه روزی درگیر این بودم که یه فیلم FullHD رو روی رسپبری‌پای با زیرنویس فارسی اجرا کنم که آخرشم نشد. (البته میخواستم اینکار رو روی Raspbian انجام بدم، OMXPlayer فیلمو خیلی خوب پخش میکرد ولی با زیرنویس فارسی مشکل داشت)

به این فکرمیکردم که چیکار کنم، یادم افتاد تلویزیون یه بخشی داره که مستقیم به یوتیوب وصل میشه ولی خب اینترنت ایران اون رو باز نمیکنه. درواقع اگر من بتونم یه شبکه‌ای داشته باشم که این قضیه دسترسی رو حل کنه! نه تنها میتونم با همون تلویزیون ویدئوهای یوتیوب رو ببینم، هرجایی که مشکلاتی از قبیل تحریم و دسترسی داشتم (مثل کنسول PS4 یا بیلد کردن پروژه‌های اندروید) با وصل شدن به این شبکه حل میشه!

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

تقریبا یکسال پیش بود که پست کوتاهی در مورد “منابع الهام بخش برای ساخت UI اپ موبایل” نوشتم و تعدادی سایت رو معرفی کردم ولی یه مشکلی وجود داشت، اونم این بود که همه‌ی UIها با زبان انگلیسی درست شده بودند و معمولا وقتی همین UI‌ها رو با زبان فارسی درست می‌کنید، درصد زیادی از زیباییشون از دست میدن. برای حل این مشکل با بچه‌های هارمس تصمیم گرفتیم خودمون زمان بذاریم و از اپ‌های اندرویدی معروف ایرانی اسکرین‌شات تهیه کنیم تا در اختیار همه‌ی برنامه‌نویسان و طراحان فارسی‌زبان بذاریم.

خروجی این تصمیم، سایت UI Screenshots شده که با آدرس http://uiscreenshots.ir میتونید بهش دسترسی داشته باشید. به دو صورت میشه تصاویر رو فیلتر کنید، روش اول با استفاده برچسب‌هایی که سمت راست صفحه لیست شده‌اند و روش دوم با استفاده از جستجوی نام برنامه‌ای که میخواهید تصاویرشو ببینید.

الان که دارم این پست رو مینویسم، تقریبا ۵۰۰ عدد اسکرین‌شات از اپ‌های معروف و زیبای ایرانی روی این سایت آپلود شده، امیدواریم که در آینده نه تنها تعداد این تصاویر بیشتر بشه بلکه بتونیم قابلیت‌های بیشتری رو در اختیار برنامه‌نویسان و طراحان ایرانی قرار بدیم.

چند وقت پیش یه AMA (فکرکنم معادل فارسیش میشه “از هرچیزی بپرس”) توی reddit بود که تیم توسعه‌دهنده‌ی دگر سوالاتی که ازشون پرسیده شده رو جواب دادن. دیشب وقت کردم بخونمش و نکاتی که بنظرم جالب رو بود رو در ادامه نوشتم. البته اگر میخواید خودتون همه‌ی سوال‌ و جواب‌هارو بخونید، میتونید به لینک زیر برید.

لینک AMA تیم دگر توی reddit

 

ضعف داکیومنت
یه سری از دولوپرها در مورد اینکه داکیومنت خوب نیست، تذکر داده بودند. چند نفر گیر داده بودن به لغت Thermosiphon که توی مثال استفاده شده :)) توشون یه انگلیسی زبان بود که نوشته بود با اینکه انگلیسی زبانم ولی این لغت رو تا حالا نشنیده بودم!

یکی از اعضای اصلی تیم توسعه‌دهنده‌ جواب داده بود که قبول دارند باید داکیومنت رو بهتر کنند. البته گفته بود پیدا کردن مثال برای توضیح دگر سخته، دلیلشم اینه اگر مثال خیلی ساده باشه، مزایای دگر رو نشون نمیده و اگر خیلی پیچیده باشه، یادگرفتنش سخت میشه. یه بخش جدید هم به اسم semantics به داکیومنت اضافه کردند و داخلش توضیح دادند دگر از چیا درست شده و واژه‌هایی که توی دگر استفاده شده معنیشون چیه.

https://google.github.io/dagger/semantics

 

انتشار نسخه ۳

یکی پرسیده بود که نسخه‌ ۳ دگر چه موقع منتشر میشه که گفته بودند تصمیمی برای این قضیه ندارند و فعلا روی همین نسخه‌ی ۲ کار میکنند.

 

دیداری‌سازی (Visualization)

دو نفر در رابطه با Visualization توی دگر پرسیده بودند. مزیت Visualization اینه میشه object graphیی که دگر ساخته رو مثل یه گراف واقعی دید و بررسی کردش.

یکی از اعضای تیم توسعه دهنده خبر از انتشار SPI رو داده بود که هدفش همین کار هست. انگار object graph رو تبدیل میکنه به فایل‌هایی با فرمت dot و میشه این فایل رو از طریق graphviz دید. البته SPI کاملا آزمایشی منتشر شده، مثال هم براش گذاشتند ولی حقیقتش من اصلا نفهمیدم چطوری میشه ازش استفاده کرد. لینک مثال

لینک مثال استفاده از SPI

 

دگر و custom views

یکی پرسیده بود که چطوری میشه از دگر توی custom viewها استفاده کرد که باز یکی از اعضای تیم توسعه دهنده گفته بود که کلا توصیه میکنیم اینکارو نکنید. dependencyهارو باید یه سطح بالاتر از view توی fragment یا Conductor یا هر کنترلر دیگه‌ای که دارید inject کنید.

 

دگر و kotlin

یکی پرسیده بود توی kotlin چطوری از دگر استفاده کنیم بهتره؟ یکی از اعضای تیم توسعه دهنده این لینک رو که منم قبلا توی بلاگ گذاشتمش رو معرفی کرد. توی این issue در مورد best practiceهای استفاده از دگر توی kotlin صحبت میکنند.

https://github.com/google/dagger/issues/900

 

ویدیو آموزشی دگر

یکی سوال پرسیده بود برای کسی که با دگر اصلا آشنا نیس، چه آموزشی رو پیشنهاد میکنید؟ یکی از اعضای تیم این لینک رو معرفی کرده بود

Understanding Dagger 2’s Generated Code

چندتا کاربر دیگه هم اینا لینک‌هارو توصیه کرده بودن

Dependency Injection Made Simple

 The Future of Dependency Injection with Dagger 2

TwistedEquations – Dagger 2 Android Tutorial

 

ماژول اندروید dagger

یکی پرسیده بود دلیل اینکه dagger.android رو منتشر کردید چیه و بعد چند پیام با یکی از اعضای تیم توسعه‌دهنده صحبت کرده. چون طولانیه، اینجا نمیذارمش و مستقیم برید توی reddit بخونیدش.

لینک به پیام‌ها توی reddit

یه جای دیگه هم یکی گفته بود حتما بجای روش قدیمی getNetComponent().inject(this توی اندروید با از dagger.android و AndroidInjection.inject(this استفاده کنیم؟ یکی از اعضای تیم توسعه‌دهنده گفته بود که میتونید از هرکدوم که میخواید استفاده کنید ولی تیم ما dagger.android رو توصیه میکنه! بعد گفته بود دلیل توصیه‌مون هم مشخصه، چون خودمون درستش کردیم :))

اگر یادتون باشه آخرین نمونه پروژه‌ای که توی گیت‌هاب گذاشتم (SingleAcitvityPattern) با زبان کاتلین نوشته شده بود. هدف اصلیم از این پروژه پیاده‌سازی الگوی Single Activity با استفاده از فرگمنت‌ها و هدف فرعیم آشنایی بیشتر با کاتلین بود. قبلا در مورد هدف اصلی یه پست بلاگ نوشتم و الان میخوام در رابطه با هدف فرعی صحبت کنم. استفاده از کاتلین زمان بیشتری ازم گرفت ولی در عوض با نکات مختلفی آشنا شدم که در ادامه براتون تعریف میکنم.

 

ترکیب کاتلین و Dagger

دیروز چندساعتی درگیر این بودم که چطوری توی پروژه‌ میتونم NavigationManager رو از طریق Dagger به فرگمنت‌ها اینجکت کنم. با توجه به ایده‌ای که در مورد NavigationManager داشتم، میشه توی یه پروژه چندتا NavigationManager داشت که هرکدوم مدیریت تعدادی از فرگمنت‌هارو به عهده داشته‌ باشه (اگر پست قبلی بلاگمو در مورد این پروژه خوندید و ایده‌مو در رابطه با NavigationManager متوجه نشدید، دلیلش اینه توضیحش توی متن سخته! شاید بعدا یه ویدیو برای توضیحش درست کردم)، این ایده استفاده از Dagger برای اینجکت کردنو خیلی سخت کرده بود. البته توی این چند ساعت، درگیر دو تا مشکل دیگه هم داشتم.

اولین مشکل این بود که وقتی Dagger رو به پروژه اضافه کردم، موقع اجرا خطای NoClassDefFoundError میداد!!! آخرش بعد از کلی تلاش و سرچ کردن، فهمیدم مشکل از من نیست! مشکل از Dagger هست و نسخه جدید ۲٫۱۴٫۱ رو فقط به خاطر حل این مشکل ریلیز کردن.😑

مشکل دوم این بود که وقتی میخواستم بصورت همزمان دو انوتیشن @inject و یه qualifire به اسم @PerFragment رو برای یه فیلد استفاده کنم، برنامه کرش میکرد!! بعد از کلی دیباگ کردن و بررسی سورس‌های جنریت شده‌ی Dagger، متوجه شدم qualifireیی که میذارم اصلا اثر نمیکنه، انگار وجود نداره!! در نهایت با سرچ کردن، فهمیدم اگر میخوام همچین کاری رو توی کاتلین بکنم، باید از یه انوتیشن به اسم @field استفاده کنم. وقتی کد رو به شکل زیر تغییر دادم، برنامه درست شد.

این نکته رو از یه issue توی ریپوی Dagger یاد گرفتم. کلا داخل این issue در مورد Best Practiceهای استفاده از Dagger توی کاتلین صحبت میکنن. نکته‌های جالبی داخلش هست.

https://github.com/google/dagger/issues/900

 

تفاوت onCreateView با onViewCreated

همون شبی که پروژه رو توی گیت‌هاب گذاشتم، شایان پوروطن لطف کرد و ۲ ۳ ساعتی در مورد جزییات پیاده‌سازی پروژه صحبت کردیم. جدای همه نکته‌هایی که ازش یاد گرفتم، یه نکته جالب و ساده هم یادم داد. قضیه این بود که من غر میزدم چرا نمیتونیم داخل متد onCreateView فرگمنت از قابلیت static layout imports کاتلین استفاده کنیم و مجبوریم بجاش کدمون رو توی متد onViewCreated بنویسم، اینجا بود که شایان بهم گفت خب درستش همینه و نه اونکاری که من تا الان میکردم😀

تا اون لحظه، هرچی سورس و مثال دیده بودم، همشون توی onCreateView کار findview رو انجام داده بودن و این باعث شده بود که فکرکنم راه درستش اینه!!! درصورتی که اشتباه بود. البته خیلی کم پیش میاد که این اشتباه باعث باگ بشه ولی بهرحال امکانش هست. دلیل اشتباه بودنش اینه که اگر layout پیچیده باشه، احتمال داره بعضی از viewها هنوز توی onCreateView ساخته نشده باشند!! برای اطمینان بیشتر باید هرکاری با view دارید، توی onViewCreated انجام بدید.

 

کشف ریپوهای کاتلینی-اندرویدی

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

اولی android-ktx که extensionهای کاربردی اندروید هست.

https://github.com/android/android-ktx

دومی kotlin-guides که راهنمای استفاده از کاتلین در پروژه‌های اندروید هست.

https://github.com/android/kotlin-guides

اول بخاطر اینکه دو هفته هس که نمیرسم “لینک‌های آخر هفته” رو توی کانال بذارم باید عذرخواهی کنم. دلیلش اینه بخاطر سربازی رفتن کارها فشرده شده و دیگه خیلی وقت نمیکنم که بلاگ‌ها و مقاله‌هایی که بنظرم جالب هستند رو بخونم. چون اولویتم کیفیت به کمیت هس، ترجیحم اینه که کلا لینکی نذارم تا اینکه بخوام لینک‌هایی که هنوز خودم نخوندمو به بقیه معرفی کنم.

حالا برسیم به اصل موضوع که چطوری میشه ارائه‌ی خوبی داشته باشیم. شرایط نسبت به سالهای گذشته تغییر کرده و رویداد‌های زیادی توی کشور برگزار میشن، بطور مثال @irlogcat که برای اندروید هس هر ماه داره برگزار میشه. در نتیجه این فرصت برای همه هست که بتونن دانششون رو در اختیار بقیه بذارن، شاید همین الان شما هم داوطلب ارائه توی یکی از این رویدادها باشید یا حداقل تصمیم گرفته باشید در آینده اینکارو بکنید. اما یه نکته‌ی مهم اینه بخاطر وجود سایت‌هایی مثل Youtube و بالا رفتن سرعت اینترنت خیلی از کسایی که توی رویدادهای داخلی شرکت میکنند، ارائه‌هایی که خارج از ایران برگزار میشن رو هم دیدن و انتظارشون بالاتر رفته. برای همین بهتره اگر میخوایم جایی ارائه بدیم، سعی کنیم با تمرین کیفیت ارائه‌مون رو بالاتر ببریم و به ارائه‌های خوب خارجی نزدیک کنیم.

یکی از نکات عجیبی که من توی توییتر میبینم، اینه که خیلیا به این قضیه افتخار میکنند که مثلا یکساعت قبل ارائه اسلایدهارو درست کردن و بعد رفتن ارائه دادن یا فقط یه روز برای آماده‌سازی کل ارائه وقت گذاشتند. بنظر من این قضیه بیشتر از اینکه نشون بده یه نفر خیلی باحال و خفن هس، نشون میده برای اونا که میخوان ارائه‌اش رو ببینن اهمیت قائل نیس. در این رابطه مقاله‌ی “How to Prepare a Talk” که در ادامه لینکشو میذارم یه نکته جالب گفته، اونم اینه که میگه برای آماده‌سازی یه ارائه حداقل باید ۲۰ساعت وقت بذارید! بعد خودش مثال زده که اگر احساس میکنید این زمان خیلی زیاده، اینجوری فکرکنید که ۵۰۰نفر ارائه‌ی ۳۰دقیقه‌ای شمارو میبینند (حضوری،آنلاین یا بعدا ضبط شده)، اگر ۵۰۰*۳۰ رو حساب کنید میشه ۱۵۰۰۰دقیقه نفر-دقیقه که همون ۲۵۰نفر-ساعت هست. حالا واقعا ارزش نداره شما ۲۰ساعت وقت بذارید تا ۲۵۰ساعت بقیه الکی هدر نره؟!

همه‌ جای مقاله‌ “How to Prepare a Talk” که خوبه ولی یه بخش دیگشم برام خیلی جالب بود، همیشه فکرمیکردم من عجیبم که خوشم نمیاد روی کاغذ نکته‌ای بنویسم و همراه خودم برای ارائه ببرم! (چون اینو به عنوان توصیه‌ی خوب برای ارائه زیاد شنیدم)، دلیلشم اینه که سعی میکنم اینقدر تمرین کنم تا با دیدن اسلایدها نکاتی که میخوام بگم یادم بیاد و اگرم نکته‌ای یادم رفته! کلا دیگه یادم بره، نه اینکه توی کاغذ یه چیزی ببینم که نوشته باشم بگم ولی یادم نیاد!!!!! درواقع دوس ندارم دیگه درگیر یه کاغذ بشم و میخوام تمرکزم همون ارائه دادن باشه. حالا وقتی این مقاله رو خوندم، فهمیدم من عجیب نیستم! واقعا این روشی هس که بعضیا استفاده میکنند. تا حالا به کسی اینکاری که خودم میکردمو توصیه نمیکردم، از این به بعد به بقیه پیشنهاد میدم چون ارائه دادن رو راحت‌تر میکنه.

حتما اگر ارائه دادن رو دوست دارید یا میخواید ارائه بدید این مقاله‌ی طولانی رو بخونید. نکاتش خیلی بیشتر از این هست که من بتونم دونه دونه بنویسم و بهتره برید خودشو بخونید.  هرچقدر ازش تعریف کنم، کم هس. تک تک نکته‌هایی که در مورد مراحل آماده‌سازی یه ارائه میگه واقعا تاثیرگذار و کاربردیه. کاشکی به جای اون مطالبی که توی درس “درس شیوه ارائه مطالب علمی وفنی” داخل دانشگاه میگن (البته از همه دانشگاه‌ها خبر ندارم،برای ما که مسخره بود)، از این جور مقاله‌ها معرفی کنن. لینک مقاله “How to Prepare a Talk”:

https://www.deconstructconf.com/blog/how-to-prepare-a-talk

توی پست قبلی در مورد الگوهای مختلف ساخت پروژه‌های اندروید صحبت کردم و خلاصه‌ای از تحقیقاتمو نوشتم. خروجی اون تحقیقات یه پروژه تمرینی براساس الگوی “تک اکتیویتی، چند فرگمنت” شده که در ادامه بیشتر در موردش توضیح میدم و میتونید از طریق گیت‌هابم به سورسش دسترسی پیدا کنید.

توی این پروژه تمرکزم روی این قضیه بوده که چطوری جا به جایی بین صفحه‌های برنامه (همون فرگمنت‌ها) رو مدیریت کنم. برای همین فعلا الگوهای معماری مثل MVP یا Dagger2 و RxJava رو قاطی پروژه نکردم. در ضمن از زبان Kotlin برای ساخت پروژه استفاده کردم تا با این زبان بیشتر آشنا بشم ولی بدیهی هس که هرکاری توی این پروژه کردم رو میشه خیلی راحت توی یه پروژه‌ی جاوایی انجام داد.

 

چالش‌ها

سعی کردم انواع چالش‌هایی که بخاطر استفاده از فرگمنت‌ها توی پروژه‌های واقعی پیش میاد رو توی این پروژه پیاده کنم تا اگر پیاده‌سازیم مشکلی داره سریعتر متوجه بشم. چالش‌هایی که به ذهنم رسید این موارد بوده: (اگر چالش دیگه‌ای به ذهنتون میرسه بهم بگید تا در موردش بیشتر صحبت کنیم)

۱- استفاده از BottomNavigationView: جدیدا در بیشتر برنامه‌ها از Bottom Navigation استفاده میشه، به همین دلیل منم برای شروع این مدل نویگیشن رو انتخاب کردم. البته در آینده میشه مثال‌ رو با navigation drawer هم پیاده کرد یا مدیریت backstack رو از حالتی که الان هست به حالتی شبیه اینستاگرام تغییر داد که هر تب برای خودش backstack جدا داشته باشه.

۲- مدیریت دکمه‌ی Back: بصورت پیشفرض این دکمه رو اکتیویتی مدیریت میکنه ولی خیلی وقتا پیش میاد بعضی از فرگمنت‌ها نیاز دارند که خودشون اینکارو به جای اکتیویتی میزبان مدیریت کنند.

۳- استفاده از Tab به همراه ViewPager در فرگمنت: گاهی پیش میاد یه فرگمنت داخلش تعدادی تب داره که هر تب خودش فرگمنت جدایی هس، توی این حالت مدیریت فرگمنت‌های داخلی به عهده‌ی اداپتر ViewPager هست

۴-  استفاده از فرگمنتی که داخلش تعدادی فرگمنت دیگه داره: در ظاهر میتونه شبیه حالت قبلی باشه ولی فرقش توی اینه مدیریت فرگمنت‌های داخلی با فرگمنت والد هست.

۵- مدیریت ویوهای داخل اکتیویتی: گاهی توی اپلیکیشن نیاز هست وقتی کاربر روی آیتمی کلیک کرد، به جزییاتش بره. توی این حالت دیگه نیاز نیست Bottom Navigation رو ببینه یا شاید لازم باشه دکمه‌ی FAB نشون داده بشه.

 

ایده‌ها

برای اینکه بتونم این چالش‌های بالارو حل کنم، از ایده‌‌های زیر استفاده کردم.

ایده اول – مدیریت جا به جایی صفحات یا همون navigation رو به یه کلاس به اسم NavigationManager سپردم. البته خیلی از مثال‌های توی گیت‌هاب اینجوری بودند. اینکار باعث رعایت شدن اصل Single Responsibility که حرف S در اصول SOLID هست میشه. این کلاس برای مدیریت navigation نیاز به یدونه FragmentManager و شناسه لیوتی که قراره کانتینر فرگمنت‌ها باشه داره. وقتی مدیریت navigation در یک کلاس جدا باشه، در آینده میشه مثلا بدون اینکه بقیه بخش‌های برنامه رو خیلی تغییر داد، بجای backstack اندروید از یه backstack کاستوم استفاده کرد. درکل دست آدمو برای توسعه‌های بعدی باز میذاره.

ایده دوم- برای اینکه بتونم ساختار تو در تو بودن فرگمنت‌هارو در جاهایی که خود فرگمنت شامل تعدادی فرگمنت دیگه باشه رو مدیریت کنم، از پیاده‌سازی Dagger2 ایده گرفتم. ایده اینه هر کلاسی که اینترفیس HasNavigationManager رو پیاده‌سازی کرده باشه وظیفه داشته باشه فرگمنت‌های داخلشو مدیریت کنه ( از ماژول اندروید Dagger2 و نحوه‌ی کمک گرفتنش اینترفیس‌های HasActivityInjector یا HasFragmentInjector الگو گرفتم). قضیه اینه هر فرگمنت وقتی داره لود میشه چک میکنه چه کسی مدیریتشو داره و ازش یه object از نوع NavigationManager میگیره تا کارهایی که نیاز داره رو انجام بده. اون کلاسی که اینترفیس HasNavigationManager رو پیاده میکنه، باید در پیاده‌سازی متد provideNavigationManager یه object از نوع NavigationManager برای فرگمنت‌های که مدیریت میکنه فراهم کنه تا اونا به روشی که گفتم ازش استفاده کنند. اینکار باعث میشه چالش ۴ راحت‌تر حل بشه و مدیریت سلسله مراتبی باشه، در نتیجه اکتیویتی میزبان همه‌ی این فرگمنت‌ها خیلی شلوغ نشه!

ایده سوم- فرگمنت‌هایی که نیاز داشته باشند دکمه‌ی back رو مدیریت کنند، میتونند متد onBackPressed رو که داخل BaseFragment هست، override کنند. اکتیوتی وقتی دکمه‌ی بک زده میشه، چک میکنه فرگمنت جاری (من فرض کردم همیشه یه فرگمنت به عنوان فرگمنت جاری باشه! این فرض رو میشه در آینده عوض کرد. الان هر فرگمنتی که آخرین بار نشون داده شده باشه میشه فرگمنت جاری) میخواد بک رو هندل کنه یا نه؟! اگر کرد که اکتیویتی کاری نمیکنه و اگر نکرد، خود اکتیویتی کار همیشگیش رو انجام میده.

ایده چهارم- برای اینکه هر فرگمنت بتونه المان‌های داخل اکتیویتی رو برای خودش مدیریت کنه، یه سری متد توی اینترفیس FragmentInteractionListener تعریف کردم. فرگمنت‌ها برای ارتباط با اکتیویتی میزبان از اینترفیس‌های خودشون مثل OnNotificationFragmentInteractionListener یا OnProfileFragmentInteractionListener استفاده میکنند که همشون از FragmentInteractionListener ارث‌بری میکنند، در نتیجه همه فرگمنت‌ها میتونن متد‌های داخل اینترفیس FragmentInteractionListener که اکتیویتی میزبانشون پیاده‌سازی کرده رو صدا بزنند.

در آخر تاکید کنم این پروژه تمرینی در حال توسعه هست و امکان داره جاهاییش اشکال داشته باشه یا حتی در آینده تغییر بکنه، در نتیجه با اینکه تلاشم اینه همه‌ی BestPracticeهارو داخلش رعایت کنم ولی فعلا زوده که خیلی خیلی مطمئن از ساختارش توی پروژه‌هاتون استفاده کنید.

میتونید سورس کامل پروژه رو توی گیت‌هابم و ریپوی SingleActivityPattern ببینید.

از وقتی اندروید رو شروع کردم، خیلی رابطه‌ی خوبی با فرگمنت نداشتم و فقط جاهایی که مجبور بودم ازش استفاده کردم. تا الانم پیش نیومده پروژه‌ای رو بطور کامل با فرگمنت درست کنم. چند وقته که خیلی وسوسه شدم به سمت استفاده‌ی بیشتر از فرگمنت برم و دو سه روزی هست که دارم روی این موضوع تحقیق میکنم. سعی کردم مقاله‌ها و سورس‌های مختلفی که به این موضوع ربط دارند رو دونه دونه بخونم و روی فرق‌هاشون فکرکنم. البته در مورد فرگمنت‌ها و مخصوصا FragmentManager هم بیشتر مطالعه کردم، تقریبا هیچ دیدی از نحوه‌ی کار FragmentManager نداشتم ولی الان خیلی بهتر شدم😃. این پست بیشتر از اینکه قرار باشه الگوی خاصی رو تایید کنه یا قضیه‌ای رو اثبات کنه، خلاصه‌ای از تحقیقات شخصیم هس که در نهایت خروجیش یه پروژه‌ی تمرینی با الگوی “تک اکتیویتی، چند فرگمنت” شده که چند روز آینده توی گیت‌هاب میذارم. ادامه …