اگر مراقب نباشید، کار با تصاویر میتواند به سرعت مشکلات عملکردی ایجاد کند. حتی یک تصویر گرافیکی کوچک با فرمت فشرده مانند JPG یا PNG میتواند هنگام رمزگشایی برای نمایش، به یک بیتمپ بزرگ تبدیل شود. اگر در نحوه استفاده از تصاویر کارآمد نباشید، ممکن است با مشکلات حافظه مواجه شوید که میتواند به عملکرد برنامه شما و سایر برنامههای روی دستگاه آسیب برساند. برای اطمینان از عملکرد بهینه برنامه خود، این بهترین شیوهها را دنبال کنید.
استفاده از کتابخانههای بارگذاری تصویر
شما میتوانید با استفاده از کتابخانههای بارگذاری تصویر مانند Coil (برای پروژههای Kotlin-first) یا Glide (برای پروژههای جاوا) کارایی برنامه خود را بهبود بخشید. این کتابخانهها با انجام کارهایی مانند ذخیره تصاویر، تغییر اندازه گرافیک در صورت نیاز و بازیافت اشیاء گرافیکی، میزان استفاده از حافظه برنامه شما را کاهش میدهند.
تغییر اندازه تصاویر در صورت لزوم
مطمئن شوید که از اندازه تصویر مناسب برای نیازهای خود استفاده میکنید. برای مثال، هرگز نباید یک تصویر بزرگ را در یک تصویر بندانگشتی کوچک بارگذاری کنید. در عوض، از روشی مانند inSampleSize برای بارگذاری یک نسخه resampled از تصویر استفاده کنید.
کتابخانههای بارگذاری تصویر مانند Coil و Glide به طور پیشفرض این نمونهبرداری مجدد را به طور خودکار برای شما انجام میدهند. میتوانید استراتژیهای کاهش نمونهبرداری آنها را با استفاده از ImageLoader (برای Coil) یا DownsampleStrategy (برای Glide) پیکربندی کنید.
منابع جایگزین را برای اندازههای مختلف صفحه نمایش ارائه دهید
اگر تصاویر را با برنامه خود ارسال میکنید، ارائه داراییهایی با اندازههای مختلف برای وضوح دستگاههای مختلف را در نظر بگیرید. این میتواند به کاهش حجم دانلود برنامه شما در دستگاهها کمک کند و عملکرد را بهبود بخشد زیرا تصویری با وضوح پایینتر در دستگاهی با وضوح پایینتر بارگذاری میشود. برای اطلاعات بیشتر در مورد ارائه بیتمپهای جایگزین برای اندازههای مختلف دستگاه، به مستندات بیتمپ جایگزین مراجعه کنید .
مستقیماً پدگذاری نکنید
گاهی اوقات ممکن است نیاز به اضافه کردن فاصله بین عناصر تصویر (padding) داشته باشید. برای مثال، ممکن است بخواهید تصویر با یک حاشیه شفاف برای ایجاد کادر حروف احاطه شده باشد. در این مواقع، فاصله بین عناصر تصویر را مستقیماً به تصویر اضافه نکنید و ابعاد تصویر را تغییر ندهید. در عوض، ابعاد تصویر را همانطور که هستند رها کنید و با استفاده از InsetDrawable ، مکان تصویر را روی صفحه تنظیم کنید. به عنوان یک روش جایگزین، میتوانید فاصله بین عناصر تصویر را در Composable یا View که تصویر را در خود نگه میدارد، اضافه کنید.
قالب پیکسلی مناسب را انتخاب کنید
با انتخاب فرمت پیکسل مناسب، بین حافظه و کیفیت تعادل برقرار کنید. وقتی به شفافیت نیاز ندارید RGB_565 استفاده کنید؛ این فرمت نصف فرمت پیشفرض ARGB_8888 از حافظه استفاده میکند.
در Glide میتوانید این را با استفاده از DecodeFormat پیکربندی کنید. در Coil، میتوانید از ویژگی bitmapConfig استفاده کنید.
در صورت امکان از بردارها استفاده کنید
برای تصاویری که از اشکال هندسی تشکیل شدهاند، یک تصویر برداری (وکتور) بسیار کوچکتر از یک بیتمپ است و به طور روان برای هر تراکم نمایشی مقیاسبندی میشود. در صورت لزوم، از عناصری مانند ShapeDrawable برای نمایش گرافیک استفاده کنید.
هر زمان که میتوانید، بیتمپها را منتشر و دوباره استفاده کنید.
فایلهای گرافیکی بزرگ میتوانند حافظه زیادی را اشغال کنند. برای کاهش تأثیر آنها، باید هر زمان که میتوانید اشیاء گرافیکی را آزاد یا دوباره استفاده کنید.
اگر از یک کتابخانه بارگذاری تصویر استفاده میکنید، مطمئن شوید که وقتی دیگر به تصاویر بیتمپ نیاز ندارید، آنها را در مخزن مدیریتشده کتابخانه منتشر میکنید. کتابخانه میتواند در صورت نیاز از اشیاء دوباره استفاده کند و یک بافر حافظه برای نیازهای آینده در دسترس نگه میدارد.
اگر گرافیکها را به صورت دستی مدیریت میکنید، باید پس از اتمام کار با بیتمپها، آنها را با فراخوانی Bitmap.recycle و حذف فوری ارجاع Bitmap ، آزاد کنید، به جای اینکه به جمعآوری زباله (garbage collection) تکیه کنید.
نکات و ترفندهای دیگر
این بخش چند روش دیگر برای بهبود عملکرد برنامه شما هنگام مدیریت گرافیک را فهرست میکند.
تصاویر بزرگ را با فایل AAB/APK خود بستهبندی نکنید
یکی از دلایل اصلی حجم بالای دانلود برنامه، گرافیکهایی است که درون فایل AAB یا APK قرار گرفتهاند. از ابزار آنالیز APK استفاده کنید تا مطمئن شوید که فایلهای تصویری بزرگتر از حد نیاز را در بستهبندی قرار نمیدهید. اندازهها را کاهش دهید یا قرار دادن تصاویر روی یک سرور و دانلود آنها فقط در صورت نیاز را در نظر بگیرید.
پیدا کردن بیتمپهای اضافی
اگر چندین کپی از یک تصویر دارید، این باعث هدر رفتن حافظه میشود. میتوانید از پروفایلر اندروید استودیو برای شناسایی گرافیکهای اضافی استفاده کنید. از تحلیلگر heap dump برای گرفتن یک heap dump استفاده کنید و با انتخاب تنظیمات bitmaps تکراری ، نتایج را فیلتر کنید.
هنگام استفاده از ImageBitmap ، قبل از ترسیم، تابع prepareToDraw را فراخوانی کنید.
هنگام استفاده از ImageBitmap ، برای شروع فرآیند آپلود بافت به GPU، قبل از رسم واقعی آن، ImageBitmap#prepareToDraw() را فراخوانی کنید. این به GPU کمک میکند تا بافت را آماده کند و عملکرد نمایش تصویر روی صفحه را بهبود بخشد. اکثر کتابخانههای بارگذاری تصویر از قبل این بهینهسازی را انجام میدهند، اما اگر خودتان با کلاس ImageBitmap کار میکنید، باید این نکته را در نظر داشته باشید.
ترجیح میدهید به جای Painter یک Int DrawableRes یا URL را به عنوان پارامتر به composable خود ارسال کنید.
با توجه به پیچیدگیهای کار با تصاویر (برای مثال، نوشتن یک تابع تساوی برای Bitmaps از نظر محاسباتی پرهزینه خواهد بود)، API Painter به صراحت با حاشیهنویسی @Stable به عنوان پایدار علامتگذاری نشده است. کلاسهای ناپایدار میتوانند منجر به ترکیبهای غیرضروری شوند زیرا کامپایلر نمیتواند به راحتی تشخیص دهد که آیا دادهها تغییر کردهاند یا خیر.
بنابراین، توصیه میکنیم به جای ارسال Painter به عنوان پارامتر، یک URL یا شناسه منبع drawable را به عنوان پارامتر به composable خود ارسال کنید.
// Prefer this:
@Composable
fun MyImage(url: String) {
}
// Over this:
@Composable
fun MyImage(painter: Painter) {
}
برای شما توصیه میشود
- توجه: متن لینک زمانی نمایش داده میشود که جاوا اسکریپت غیرفعال باشد.
- ImageBitmap در مقابل ImageVector {:#bitmap-vs-vector}
- ذخیره وضعیت رابط کاربری در Compose
- مراحل نوشتن Jetpack