روش بهینه نمایش عکس در Xamarin Forms
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: چهار دقیقه

پیشاپیش از شما دعوت می‌کنم اگر از سایر روش‌های توسعه برنامه‌های موبایل چون Flutter ،React native و ... استفاده می‌کنید نیز این مقاله را مطالعه کنید؛ چرا که ایده کلی و نکات مهم آن می‌تواند برای شما نیز مفید باشد.

زمانیکه شما از طراح، کاری را می‌گیرید و فرضا می‌خواهید در صفحه‌ای از برنامه موبایل، یک لیوان را نمایش دهید، به شما یک فایل png یا svg تحویل داده می‌شود. اگر چه عموما روش‌هایی وجود دارند تا همان فایل را به صورت مستقیم در صفحه برنامه خود استفاده کنید، ولی این کار به چند دلیل توصیه نمی‌شود:
۱- دستگاه‌های مختلف، Resolution‌های متفاوتی دارند و سخت‌افزار بعضا ضعیف موبایل، باید عکس را برای نمایش بهینه، Scale کند که عملی است هدر دهنده پردازنده و حافظه.
۲- حتی وقتی عمل Scale انجام شد، وقتی صفحه مربوطه بسته شود و به صفحه دیگری برویم، در باز کردن دوباره صفحه مربوطه، این عمل هزینه بر مجددا رخ می‌دهد.

برای حل این مشکل، می‌توان دو قدم برداشت:
قدم اول اینکه عکس svg و یا png آن لیوان را در Scaleهای مختلف، از پیش ذخیره کرد. این کار خود دو اشکال دارد. یک اینکه اگر این عمل به صورت دستی انجام شود، احتمال اشتباه بالا می‌رود و انجام این کار برای Android/iOS/Windows و برای Scaleهای مختلف، برای هر عکس، نیاز به ذخیره لااقل یک دو جین عکس دارد. دوم اینکه با ذخیره‌سازی چند باره یک عکس در Scaleهای مختلف، حجم فایل نهایی پروژه بالا می‌رود.

برای خودکاری سازی این فرآیند دستی، در Xamarin Forms، React native و ... ابزارهایی تعبیه شده است که ResizetizerNT نمونه Xamarin Forms آن است که یک عکس svg یا png را از شما گرفته و در Scaleهای مختلف، برای Android/iOS/Windows ذخیره می‌کند و طبیعتا احتمال اشتباه کم می‌شود و کار بسیار ساده می‌شود.

برای حل مشکل سایز خروجی نهایی، در Android و Google Play Store فرمت جدیدی جایگزین apk شده است به نام aab یا Android App Bundle که با توجه به Resolution دستگاهی که در حال دانلود برنامه است، فایلی را برای وی ساخته و می‌فرستد که فقط عکس‌های با Scale مناسب در آن است؛ پس می‌توانیم لااقل در Android نگران حجم نباشیم.
البته تاثیر این‌کار در Performance آن‌چنان بالاست که بهتر است برای Storeهای متفرقه که از aab پشتیبانی نمی‌کنند و کماکان فقط از apk پشتیبانی می‌کنند نیز کماکان عکس در Scaleهای مختلف ذخیره شود.

در iOS نیز ابزار pngcrunch وجود دارد که عکس‌های png را بهینه و compress می‌کند و در کاهش حجم فایل نهایی مؤثر است. در Xamarin.iOS در قسمت تنظیمات پروژه، در قسمت iOS Build، زدن تیک Checkbox مربوطه با نام Optimize PNG images به معنای درخواست استفاده از این ابزار مفید است.

با این حال، حتی اگر عکس‌ها در Scaleهای مختلفی ذخیره شوند، مرحله‌ای وجود دارد که آن png، به bitmap قابل نمایش تبدیل می‌شود. این عمل نیز هزینه‌بر بوده و زمانیکه شما صفحه ای را بسته و مجددا باز می‌کنید نیز این عمل تکرار می‌شود. همچنین اگر در یک List view پنج آیتم را داشته باشید که یک عکس را دارند، این عمل پنج بار تکرار می‌شود.

در Android ابزاری معرفی شده‌است که Glide نام دارد و این ابزار، مرحله تبدیل png به bitmap قابل نمایش را cache می‌کند و دیگر باز و بسته کردن صفحات، یا استفاده از یک عکس در List view، اشکالی را ایجاد نمی‌کند. در Xamarin Forms با استفاده از GlideX.Forms، می‌توانید کاری کنید که در Android این بهینه سازی بسیار مؤثر صورت پذیرد و به Scroll نرم در List view و باز شدن سریع صفحات برسید. در iOS معادل همین کار را کتابخانه مطرح Nuke انجام می‌دهد که برای استفاده از آن در Xamarin Forms میتوانید از این Package استفاده کنید.
مزیت دیگر استفاده از GlideX.Forms و Nuke در این است که اگر جایی از برنامه، عکس‌هایی را از سرور دریافت و نمایش دهید (مثلا عکس مشتری‌ها در لیست مشتریان)، این دو ابزار عکس مربوطه را پس از Scale شدن و تبدیل شدن به Bitmap برای استفاده‌های بعدی Cache می‌کنند و سری بعد که نیاز به نمایش همان عکس می‌شود، به جای Scale شدن مجدد و تبدیل شدن به Bitmap دوباره، فقط از Cache محتوای آماده به نمایش به کاربر نمایش داده می‌شود.

در نهایت شما با چند خط تنظیمات ساده و نصب کردن چند package می‌توانید با داشتن یک svg یا png، آن‌را به بهینه‌ترین شکل ممکن در Android/iOS/Windows نمایش دهید.
این پروژه در Github تمامی این موارد را در کنار هم گردآوری کرده‌است که می‌توانید از سورس آن نیز برای درک بهتر موارد استفاده کنید.
    • #
      ‫۴ سال و ۵ ماه قبل، پنجشنبه ۷ فروردین ۱۳۹۹، ساعت ۱۷:۴۶
      بله، من هم زمانی از این افزونه استفاده می‌کردم. که البته الآن موضوعیت سابق رو نداره و بسیاری از امکاناتش الآن داخل خود Xamarin Forms هست.

      ۱- جدیدا خود Xamarin Forms Image می‌تونه gif نشون بده.
      ۲- زمانی که به یه Image یک Uri بدیدم، دیگه خودش Cache می‌کنه و هر سری از سرور نمی‌گیره.
      ۳- عملکرد Glide و Nuke تا دو برابر بهینه‌تر هست.
      ۴- در صورتی که قصد استفاده از Svg داشته باشیم هم ResizetizerNT اون رو پشت صحنه تبدیل به png می‌کنه.
      ۵- Image در خود Xamarin Forms الآن Font رو هم قبول می‌کنه، مثل FontAwsome و ...
  • #
    ‫۴ سال و ۵ ماه قبل، یکشنبه ۱۰ فروردین ۱۳۹۹، ساعت ۲۳:۳۴
    آیا برای برنامه‌های موبایل هیبریدی هم راه حلی دارید ؟ 
    • #
      ‫۴ سال و ۵ ماه قبل، دوشنبه ۱۱ فروردین ۱۳۹۹، ساعت ۲۰:۰۶
      تجربه ای در این زمینه ندارم، ولی با همین مسیر کلی که عرض کردم و مثال Xamarin Forms اش رو پیاده سازی کردم، قطعا باید بتونید راه حلی پیدا کنید. یعنی عکس رو به صورت svg داشته باشید و ابزاری به صورت خودکار اون رو به پنج حالت اصلی تبدیل کنه و پنج تا png نشون بده و تو فولدرهای مربوطه تو پروژه اندروید بگذاره و نمایش عکس کار کنه. البته توی Hybrid دیگه استفاده از Glide و Nuke معنی نمیده، ولی در عوض اگه هدف پشتیبانی از دستگاه‌های خیلی قدیمی نباشه، خود svg‌ها رو هم میشه نشون داد.