مهم‌ترین سوالات مصاحبه استخدامی از توسعه‌دهندگان اندروید

نویسنده : سید ایوب کوکبی ۶ بهمن ۱۳۹۷

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

۱- فرق بین implicit intent و explicit intent چیست؟

در explicit intent این ما هستیم که به سیستم‌عامل دستور می‌دهیم کدام اکتیویتی یا کامپوننتِ سیستمی به intent ارسال شده پاسخ دهد. از سوی دیگر در implicit intent فقط اکشن مد نظرمان را اعلام می‌کنیم و خودِ اندروید کامپوننت‌هایی که قادر به هندل کردن آن فعالیت هستند را مشخص می‌کند. در اغلب مواقع از explicit intentها برای هندل کردن کامپوننت‌های داخل برنامه استفاده می‌شود و از implicit intentها نیز برای ارتباط بین اپلیکیشن‌های مختلف استفاده می‌کنیم. به عنوان مثال وقتی قرار است تصویری را مشاهده کنیم، سیستم‌عامل اندروید گالری پیش‌فرض گوشی و تمامی اپلیکیشن‌هایی که قادر به نمایش تصویر هستند را فهرست می‌کند تا کاربر یکی از برنامه‌ها را جهت نمایش تصویر انتخاب کند.

۲- چه زمانی از فرگمنت به جای اکتیویتی استفاده می‌کنید؟

این سوال تقریباً سوژه بسیاری از مصاحبه‌هاست. برای نمایش یک اکتیویتی جدید، اکتیویتی قبلی بایستی destroyed, pause و stopped شود. بهترین پاسخ این است که تنها زمانی از اکتیویتی استفاده می‌شود که لازم است کل صفحه را تغییر دهیم. هر جای دیگری که تنها بخشی از صفحه باید تغییر کند از فرگمنت استفاده می‌کنیم. هر یک از سناریوهای پایین هم قابل قبول است:

  • وقتی قسمت‌های از واسط کاربری بین اکتیویتی‌های مختلف مشترک است؛
  • وقتی قرار است ویوهای مشخصی را سوایپ کنید؛
  • وقتی قرار باشد دو layout را به صورت همزمان کنار هم نشان دهید؛
  • وقتی داده‌هایی دارید که لازم است بین اکتیویتی‌های مختلف ثابت بماند (یعنی از فرگمنت‌هایی که این داده‌ها را نگه‌داری می‌کند استفاده کنیم).

۳- از یک فرگمنت به فرگمنت دیگر سوئیچ می‌کنید، از کجا معلوم، کاربر با دکمه Back به فرگمنت قبلی بازگردد؟

این سوال نشان می‌دهد که توسعه‌دهنده درباره چرخه حیات داینامیک فرگمنت‌ها، Fragment Transaction و back stack چه میزان اطلاعات دارد. وقتی قرار است با زدن دکمه Back فرگمنت قبلی باز شود، لازم است قبل از ()commit کردن، هر یک از Fragment transactionها را با فراخوانی ()addToBackStack در back stack ذخیره کنیم. قطعاً توسعه‌دهنده اینجا نبایستی پیشنهاد ساخت یک Back Button مجزا دهد ولی اشاره به این موضوع که نباید FragmentTransaction را بعد از فراخوانی ()onSaveInstanceState کامت کرد چون منجر به بروز استثناء می‌شود، امتیاز محسوب می‌شود.

۴- چگونه بدون استفاده از کلاس thread یک برنامه مالتی‌ترد درست می‌کنید؟

در صورتی که فقط لازم است متد ()run را override کنیم با Runnable این کار را انجام می‌دهیم.

بخوانید  آشنایی با مفهوم Solid در برنامه نویسی اندروید

۵- ThreadPool چیست؟ و آیا از به کارگیری چندین ترد جدا کارآمدتر است؟

ThreadPool شامل صفی از وظایف و گروهی از worker thread ها بوده که اجازه اجرای چندین نمونه از یک تسک را میسر می‌کند. هدف از این سوال در مصاحبه، اطمینان از میزان شناخت توسعه‌دهنده از تاثیر خوب چند نخی روی برنامه و اثر منفی آن در صورت استفاده نادرست از آن است. استفاده از ThreadPool کارآمدتر از این است که منتظر اجرای چند عمل روی یک نخ مستقل باشیم. همچنین با استفاده از ThreadPool دیگر نیازی نیست هر وقت به یک worker thread نیاز داشتیم، ترد جدیدی را ایجاد یا نابود کنیم.

۶- چه ارتباطی بین چرخه حیات AsyncTask و چرخه حیات اکتیویتی وجود دارد؟ و چه مشکلات بالقوه‌ای وجود دارد؟

AsyncTask به چرخه حیات اکتیویتی‌ای که به آن تعلق دارد گره نخورده است. وقتی اکتیویتی نابود یا اصطلاحاً destroyed شده و مجددا ساخته می‌شود، AsyncTask از بین نمی‌رود. این موضوع می‌تواند از جهاتی مشکل‌آفرین باشد. اما نکات مهمی که توسعه‌دهنده بایستی در جریان مصاحبه به آن‌ها اشاره کند شامل موارد ذیل است:

  • AsyncTask به محض کامل شدن، تلاش می‌کند تا نمونه قبلی اکتیویتی را بروزرسانی نماید و چون نمونه قبلی وجود ندارد خطای IllegalArgumentException صادر می‌شود؛
  • از آنجایی که AsyncTask ارجاعی به نمونه قبلی اکتیویتی را نگه‌داری می‌کند، آن اکتیویتی هیچگاه توسط مکانیزم Garbage Collector پاکسازی نمی‌شود که نتیجه‌اش نشت حافظه خواهد بود.

راه‌حل این است که برای تسک‌های طولانی که قرار است در زمینه اجرا شوند به هیچ عنوان از AsyncTask استفاده نکنیم.

۷-  چگونه به داده‌های موجود در ContentProvider دسترسی پیدا می‌کنید؟

برای اینکار ابتدا از داشتن پرمیژن خواندن (Read Access Permission) مطمئن می‌شویم. سپس با فرخوانی متد ()getContentResolver روی شی Context و نهایتاً فرخوانی متد ()ContentResolver.query داده‌ها را دریافت می‌کنیم. متد ()ContentResolver.query یک کرسر (Cursor) برمی‌گرداند. بنابراین با متدهای کرسر می‌توانید هر ستونی از اطلاعات را به صورت مجزا دریافت کنید. دستیابی به داده‌ها جزء کارهایی محسوب می‌شود که به راحتی می‌تواند ترد main را مشغول کند. به همین دلیل معمولا فرخوانی این متدها در ترد دیگری صورت می‌گیرد تا احیاناً با بلاک شدن ترد اصلی برنامه مواجه نشویم.

۸- فرق بین Serializable و Parcelable چیست؟

Serializable اینترفیسی استاندارد در زبان جاوا بوده که به خاطر نداشتن هیچ متدی به راحتی در هر برنامه‌ای می‌توان از آن استفاده کرد. صرفنظر از پیاده‌سازی راحت Serializable، این اینترفیس به خاطر استفاده از reflectionهای جاوا، معمولاً تعداد زیادی اشیاء موقت ایجاد می‌کند. از سوی دیگر Parceable برای اکوسیستم اندروید بهینه‌سازی شده است و سرعتش نسبت به Serializable بالاتر است. بعلاوه به صورت کامل قابل شخصی‌سازی است طوری که با استفاده درست از آن می‌توان کمترین اشیاء موقت را در حافظه ایجاد کرد. اگرچه پیاده‌سازی Parceable مستلزم کار بیشتری است ولی اغلب برنامه‌نویسان به خاطر مسائل بهینه‌سازی و پرفرمنس چاره‌ای جزء استفاده از آن ندارند.

بخوانید  20 ترفند برای بهبود رابط کاربری برنامه‌های موبایل

۹- Adapter چیست؟

برای اتصال به ListView, GridView و سایر AdapterViewها به کامپوننتی تحت عنوان Adapter نیاز داریم که واسط بین دیتاسورس و AdapterView است. در واقع آداپتور همانند پلی است که هر کدام از مدخل‌های داده‌ای را از دیتاسورس گرفته و به شکل مناسبش در AdapterView نمایش می‌دهد.

۱۰- خطای معروف ANR یا Application Not responding چه بوده و برای بروز نکردن این خطا در برنامه‌تان چه می‌کنید؟

هدف مصاحبه کننده از این سوال این است که اطمینان حاصل کند توسعه‌دهنده از قانون طلایی چندنخی در اندروید آگاه هست یا نه. این قانون می‌گوید: هیچگاه عملیات طولانی و سنگین را در ترد اصلی برنامه یعنی main انجام ندهید. خطای ANR زمانی رخ می‌دهد که واسط کاربری برنامه (UI) به مدت ۵ ثانیه به حالت Unresponsive در بیاید. این موضوع اغلب به خاطر مسدود شدن ترد main اتفاق می‌افتد. برای مقابله با آن سعی کنید تا حد امکان کارها را از main خارج کرده و در صورت لزوم از تردهای دیگر استفاده کنید.

۱۱- فرایند ساخت یک Custom View را شرح دهید.

این موضوع پیچیده بوده، بنابراین تنها بیان کلیات کفایت می‌کند. البته اینکه باید کلاس View را اکستند کنیم حتما بایستی اشاره شود. بعد از اکستند کردن کلاس مورد نظر، کارهای زیر را باید انجام دهیم:

  • ساخت فایل‌های res.xml, values.xml, attr.xml و تعریف attribute هایی که می‌خواهید در کاستوم ویوی خود از آن‌ها استفاده کنید؛
  • در کلاس ویو، متد سازنده‌ای را اضافه کنید، شی Paint را نمونه‌سازی کرده و attributeهای کاستوم را دریافت نمایید؛
  • یکی از متدهای ()onMeasure یا ()onSizeChanged را Override کنید؛
  • ویویتان را با override کردن متد ()onDraw ترسیم کنید.

۱۲- BuildType در گریدل چیست و چه کاربردی دارد؟

Build Types پراپرتی‌هایی را تعریف می‌کند که گریدل در فرایند بیلد و پکیج کردن برنامه از آن‌ها استفاده می‌کند.  هدف سوال این است که بداند توسعه‌دهنده تفاوتی بین Product flavors, Build Variants, Build Types قائل می‌شود یا نه. چون معمولاً توسعه‌دهنده‌ها این‌ها را با هم اشتباه می‌گیرند.

  • Build Type چگونگی ساخت ماژول را توصیف می‌کند. مثلاً پروگارد در فرایند بیلد اجرا شود یا نه؛
  • Product Flavor چیزی که باید ساخته شود را مشخص می‌کند، مثلاً کدام ریسورس در بیلد وجود داشته باشد؛
  • گریدل برای هر ترکیبی از Product falvor و Build type های پروژه، Build Variant تولید می‌کند.

۱۳- تفاوت اصلی ListView و RecyclerView چیست؟

این دو تفاوت‌های زیادی با هم دارند ولی چیزی که در مصاحبه مهم است تا به آن اشاره کنید دو مورد زیر است:

  • الگوی ViewHolder در ListView کاملاً اختیاری است ولی در RecyclerView خیر؛
  • ListView فقط از اسکرول عمودی پشتیبانی می‌کند، در صورتی که RecyclerView چنین محدودیتی ندارد.

۱۴- به صورت کوتاه راه‌های بهینه‌سازی ویو را بیان کنید

روش‌های مختلفی برای این کار وجود دارد ولی موثرترینشان عبارتند از:

  • بررسی overdraw بیش از حد: به این صورت که برنامه را روی دستگاه اندرویدی نصب کرده و گزینه Debug GPU Overview را فعال کنید؛
  • فلت کردن سلسله‌مراتب ویو: ساختار سلسله‌مراتبی view را به کمک ابزار Hierarchy Viewer در اندروید استودیو بازبینی کنید.
بخوانید  آموزش زبان کاتلین – درس 26 (Sealed Class)

اندازه‌گیری کنید که هر یک از مراحل measure، layout و draw چقدر طول می‌کشد. با ابزار Hierarchy Viewer نیز می‌توانید هر جایی از پایپ‌لاین رندرینگ واسط گرافیکی را بررسی کرده و قسمت‌هایی که نیاز به بهینه‌سازی دارند را پیدا کنید.

۱۵- Handler معمولاً برای چه منظوری استفاده می‌شود؟

از هندلر برای ارتباط بین تردهای مختلف استفاده می‌شود و غالباً برای پاس دادن یک اکشن از ترد زمینه به ترد اصلی اندروید به کار می‌رود. این سوال بخش دیگری از توانایی توسعه‌دهنده در استفاده از چندنخی را ارزیابی می‌کند. اینکه نمی‌توان به جزء ترد اصلی برنامه از تردهای دیگر برای بروزرسانی UI استفاده کرد نکته مهمی است که توسعه‌دهنده حتماً باید در مصاحبه به آن اشاره کند.

۱۶- گام‌های لازم برای bound کردن سرویس‌ها از طریق زبان توصیف واسط (AIDL) را توضیح دهید

  • یک اینترفیس AIDL در فایل aidl. تعریف می‌کنیم؛
  • این فایل را در فولدر src اپلیکیشنِ میزبان و هر اپلیکیشن دیگری که قرار است به سرویس مورد نظر بایند شود، ذخیره می‌کنیم؛
  • برنامه را Build کرده و بدین‌ترتیب ابزار Android SDK یک فایل IBinder interface را در فولدر gen تولید می‌کند؛
  • اینترفیس فوق را با اکستند کردن اینترفیس Binder و پیاده‌سازی متدهای به ارث رسیده از فایل aidl. پیاده‌سازی می‌کنیم؛
  • سرویس را اکستند کرده و متد ()onBind را برای برگرداندن پیاده‌سازی زیرکلاس، Override می‌کنیم.

۱۷- فرق بین ()onCreate و ()onStart چیست؟

متد ()onCreate تنها یکبار در چرخه حیات اکتیویتی ایجاد می‌شود. وقتی اکتیویتی به دلایلی مثلا تغییر کانفیگ سیستم (مثل چرخاندن صفحه، یا عوض شدن زبان گوشی و …) نابود می‌شود این متد فرخوانی میشود. متد ()onStart هر وقت اکتیویتی به کاربر نمایش داده میشود فرخوانی میشود و معمولاً بعد از ()onCreate یا ()onRestart اجرا می‌شود. چرخه حیات اکتیویتی و فرگمنت جزء مهمترین مفاهیمی هستند که در سوالات استخدامی نیز به کرات سوال خواهد شد چرا که درک درست این متدها برای ساخت یک اپلیکیشن ضروری است. برای کسب اطلاعات بیشتر به این صفحه از گیت‌هاب مراجعه کنید.

۱۸- چه زمانی ممکن است از FrameLayout استفاده کنید؟

از FrameLayout زمانی استفاد می‌کنیم که ویوی ما فقط شامل یک آیتم باشد. وقتی چندین آیتم مختلف را به FrameLayout اضافه کنید، همگی بر روی یکدیگر انباشت می‌شوند. بنابراین یکی دیگر از کاربردهای FrameLayout زمانی است که نیازمند ovelape کردن ویوها هستید؛ مثلاً زمانی که می‌خواهید عناصری را روی عناصر دیگر Overlay کنید.

جمع‌بندی مصاحبه استخدامی برای توسعه‌دهندگان اندروید

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

سید ایوب کوکبی

نویسنده و مترجم...

1 دیدگاه

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *




    هادی

    شنبه ۱۹ مرداد ۱۳۹۸

    سپاس بخاطر مطالب مفیدتون.