نوشتن layoutهای کارآمد در اندروید

آفلاین
user-avatar
پوریا شریفی
16 مهر 1399, خواندن در 7 دقیقه

با پیچیدگی روزافزون برنامه‌های تلفن همراه، شما همیشه می‌خواهید از نظرات کاربران مانند "این برنامه بدرد نخور" یا "این برنامه بر روی دستگاه کند است" جلوگیری کنید. بنابراین امروز می‌خواهیم بدانیم که چیدمان‌های پیچیده چطور می‌تواند باعث این رفتاها از کاربر شود و در نهایت نکاتی در مورد نوشتن چیدمان‌های کارآمد می‌گوییم.

اهمیت layout

نرخ تازه‌سازی در اکثر تلفن‌های همراه 60 فریم بر ثانیه است، بنابراین ما فقط 1.6 برابر با 16 میلی‌ثانیه برای ارائه یک فریم و جلوگیری از هرگونه رفتار دیگر از برنامه داریم. بنابراین بهینه سازی حتی 1 میلی‌ثانیه می‌تواند دستاوردهای بزرگی را فراهم کند.

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

بیایید نگاهی به برخی از سناریوهایی که منجر به این اتفاق می‌شود بیاندازیم:

  • یک LinearLayout با layout_weight که هر فرزند نیاز به دوبار اندازه گیری دارد.
  • GridLayout با weight یا fill gravity باعث می‌شود تمام مزایای قبل از پردازش از بین برود.
  • RelativeLayout همیشه حداقل به دو پاس نیاز دارد

حال این سوال مطرح می‌شود که چرا چیدمان‌های تو در تو بد است؟ تصور کنید که یک چیدمان سلسله مراتبی تو در تو در یک RecyclerVIew دارید؛ هزینه اکنون با تعداد موارد ضرب می‌شود و این همان چیزی است می‌تواند منجر به ارائه یک فریم بیش از 16 میلی‌ثانیه شود.

تشخیص مشکل

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

  • Layout Inspector: نمایش بصری از سلسله مراتب طرح شما در component tree است که می‌تواند برای تعیین عمق یک طرح خاص استفاده شود، بنابراین viewهای والد بدون استفاده را حذف می‌کند.
  • Lint: شامل مجموعه‌ای از قوانین مفید است که می‌تواند مشکلات چیدمان را برجسته کرده و پیشنهادات مفیدی نیز برای رفع آن‌ها ارائه دهد.
  • Systrace: به شما کمک می‌کند تا تمام فرایندهای در حال اجرا موجود در برنامه را به شکل نمودار مشاهده کنید. این به شما کمک می‎‌کند تا فرایندی که بیش‌تر از زمان معمول برای اجرا زمان برده است پیدا کنید. برای چیدمان می‌خواهیم اطمینان حاصل کنیم که رسم چیدمان، پیمایش و اندازه‌گیری در 16 میلی‌ثانیه کامل شود.
  • Android Profiler: یکی از بهترین ابزارهایی که به شما کمک می‌کند تا اطلاعات زیادی راجع به آنچه در برنامه شما در پشت صحنه اتفاق می‌افتد جمع کنید، و در قالب یک نمایش گرافیکی به همراه زمان سپری شده توسط هر فرایند تا پایان آن‌ها به نمایش می‌گذارد. همچنین امکانcapture trace را در برنامه به شما می‌دهد، بسیار شبیه به systrace. برای بهینه سازی چیدمان‌ها، بر استفاده از cpu نظارت کنید و به دنبال فریم‌های قرمز در نمودار باشید، این‌ها مواردی هستند که باعث ایجاد رفتارهای بد در برنامه می‌شوند.

بیایید نگاهی به چند مورد که می‌تواند در بهینه‌سازی چیدمان کمک کند بیاندازیم:

استفاده مجدد از چیدمان‌ها

استفاده از تگ <include> یک کار معمول است، با اینحال می‌تواند باعث تو در تو شدن غیر ضروری شود. بیایید ببینیم چگونه باعث این اتفاق می‌شود:

بیایید فرض کنیم که یک هدر قابل استفاده مجدد تعریف کرده‌اید و با استفاده از تگ <include> آن را به اکتیویتی اضافه کرده‌اید. در اینجا کدها خواناتر هستند و همچنین می‌توان مجدد از آن‌ها استفاده کرد، بسیار عالی است!. بیایید ببینیم که سیستم چگونه آن را تفسیر می‌کند: کامپایلر تگ <include> را با فایل layout جایگزین می‌کند، بنابراین در این حالت Constraint-Layout تو در تو خواهیم داشت.

یک راه بسیار سریع وساده برای جلوگیری از این مشکل وجود دارد، و آن استفاده از تگ <merge> است. فقط کافیست تگ ConstraintLayout را در layout_header.xml با تگ merge جایگزین کنید. برای اینکه ببینید که view شما هنگام اضافه شدن layout والد(activity_home.xml) چگونه تراز خواهد شد، می‌توانید از ویژگی tools:parentTag استفاده کنید تا viewGroup والدی که این طرح در آن قرار می‌گیرد را مشخص کنید، همین!. با این کار Ui موجود در ویرایشگر طوری به نظر می‌رسد که انگار در viewGroup اضافه شده است.

Layout_header_optimised.xml نیز همانند layout_header.xml اضافه خواهد شد.

بیایید ببینیم که سیستم چگونه آن را تفسیر می‌کند: کامپایلر تمام عناصر (در این حالت <TextView>) را مستقیماً درون تگ merge در طرح قرار می‌دهد. Constraint-Layout تو در تو که قبلا دیدیم اکنون از بین رفته است. این جادوی تگ merge است.

طرح ارزان‌تری انتخاب کنید

گاهی اوقات تو در تو شدن بر روی طرح والد شما اثر می‌گذارد. طرح‌های والد را هوشمندانه انتخاب کنید. به عنوان یک قاعده کلی می‌توانید از این دستورالعمل پیروی کنید:

  • پیچیدگی  ـــــــــــــــ   ConstraintLayout
  • عناصر پشت‌هم به صورت عمودی یا افقی   ـــــــــــــــ   LinearLayout
  • قرار دادن viewها بر روی هم  ـــــــــــــــ   FrameLayout
  • از استفاده RelativeLayout خودداری کنید

نکته: در نسخه N اندروید، constraintlayout عملکردی مشابه به relativelayout اما با هزینه کمتری ارائه می‌دهد.

تاخیر در بارگیری viewها

گاهی اوقات برنامه شما از طرح‌بندی استفاده می‌کند که هنگام inflate شدن بر روی صحفه مشاهده نمی‌شود. این‌ها viewهایی هستند که می‌خواهید در آینده براساس تعاملات کاربر نشان دهید. برخی از نمونه‌های آن می‌تواند یک progress indicator، undo messages و... باشد. شما می‌توانید آن‌ها را فقط در صورت لزوم ارائه دهید. این باعث کاهش استفاده از حافظه و تسریع در ارائه طرح شود. اما چگونه این کار را انجام دهیم؟ می‌توانید با استفاده از ViewStub زمان بارگیری view را کاهش دهید.

نکته: ViewStub نمایی سبک و بدون بُعد است که چیزی را ترسیم نمی‌کند و در طرح شرکت نمی‌کند. به همین ترتیب، برای inflate کردن بسیار ارزان است.

بارگیری ViewStub

وقتی می‌خواهید طرح مشخص شده توسط ViewStub را بارگیری کنید، یا با فراخوانی setVisibility(View.VISIBLE) آن را مشاهده کنید یا inflate() را صدا بزنید. اگرچه روش inflate() این مزیت را دارد که view ریشه از طرح inflate شده را برمی‌گرداند.

بسیار مهم است که به یاد داشته باشید که پس از inflate شدن stub، stub از سلسله مراتب view حذف می‌شود. بنابراین ارجاع به progress_stub اکنون null برمی‌گرداند. ViewStub سازش بزرگی بین سهولت برنامه‌نویسی و کارایی است. تنها اشکال آن این است که در حال حاضر از تگ merge پشتیبانی نمی‌کند.

نتیجه

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

  • کد خود را پروفایل کنید و به دنبال فریم‌های قرمز باشید
  • از تو در تو شدن خودداری کنید و از <merge> استفاده کنید
  • از layoutهای ارزان استفاده کنید: ConstraintLAyout را بهترین دوست خود بدانید
  • تاخیر در بارگیری layoutها و استفاده از ViewStub

همه چیزهای خوب قیمت دارند

بهینه‌سازی طرح‌بندی‌ برای برنامه‌های پیچیده بسیار خوب است، اما چند نکته  وجود دارد که باعث سربار برای برنامه‌های ساده با طرح‌های ساده‌تر می‌شود. قبل از اینکه در بهینه‌سازی طرح‌های خود عمیق شوید نکات زیر را بخاطر داشته باشید:

  • DataBinding از تگ merge پشتیبانی نمی‌کند
  • ViewStub فقط زمانی مفید است که شما آن طرح را بلافاصله روی صحفه نمی‌خواید و موارد بسیار کمی را ارائه می‌دهد
  • گفتن پروفایل کردن کد آسان‌تر از انجام دادن آن است

منبع

چه امتیازی به این مقاله می دید؟
خیلی بد
بد
متوسط
خوب
عالی

دیدگاه‌ها و پرسش‌ها

برای ارسال دیدگاه لازم است، ابتدا وارد سایت شوید.

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

آفلاین
user-avatar
پوریا شریفی @pouryasharifi78
ابتدا که با برنامه‌نویسی آشنا شدم به سمت php و طراحی وب رفتم، بعد از اون به توسعه‌ی اندروید علاقه‌مند شدم و تقریبا ۲ سال است که مشغول به برنامه‌نویسی...
دنبال کردن

گفتگو‌ برنامه نویسان

بخشی برای حل مشکلات برنامه‌نویسی و مباحث پیرامون آن وارد شو