আপনি সতর্ক না হলে, ছবি নিয়ে কাজ করার সময় দ্রুত পারফর্ম্যান্স সংক্রান্ত সমস্যা দেখা দিতে পারে। এমনকি JPG বা PNG-এর মতো কম্প্রেস করা ফর্ম্যাটে থাকা ছোট গ্রাফিকও ডিসপ্লে করার জন্য ডিকোড করা হলে বড় বিটম্যাপে পরিণত হতে পারে। আপনি যদি গ্রাফিক্স ব্যবহারের ক্ষেত্রে দক্ষ না হন, তাহলে মেমরি সংক্রান্ত সমস্যা হতে পারে যা আপনার অ্যাপ এবং ডিভাইসের অন্যান্য অ্যাপের পারফর্ম্যান্সকে প্রভাবিত করতে পারে। আপনার অ্যাপ যাতে সবচেয়ে ভাল পারফর্ম করে তা নিশ্চিত করতে এইসব পেশাদার পদ্ধতি অনুসরণ করুন।
ছবি লোড করার লাইব্রেরি ব্যবহার করুন
আপনি Coil (Kotlin-ফার্স্ট প্রোজেক্টের জন্য) বা Glide (Java প্রোজেক্টের জন্য)-এর মতো ইমেজ লোডিং লাইব্রেরি ব্যবহার করে আপনার অ্যাপের কার্যকারিতা উন্নত করতে পারেন। এই লাইব্রেরিগুলি আপনার অ্যাপের মেমরির ব্যবহার কমিয়ে দেয়, যেমন ছবি ক্যাশে করা, প্রয়োজন হলে গ্রাফিক্স ডাউনস্যাম্পল করা এবং গ্রাফিক অবজেক্ট রিসাইকেল করা।
ইমেজ ডাউনস্যাম্পেল করুন
আপনার প্রয়োজন অনুযায়ী সঠিক সাইজের ছবি ব্যবহার করতে ভুলবেন না। ছোট কন্টেনারে (যেমন থাম্বনেল) বড়, হাই-রেজোলিউশনের ছবি লোড করা এড়িয়ে চলুন। পরিবর্তে, মেমরিতে ডিকোড করার আগে ইমেজ স্কেল ডাউন করতে ডাউনস্যাম্পলিং ব্যবহার করুন।
ক্লায়েন্ট-সাইড ডাউনস্যাম্পলিং
Coil এবং Glide-এর মতো ইমেজ লোডিং লাইব্রেরি আপনার জন্য ডাউনস্যাম্পলিং অটোমেটিক
ম্যানেজ করে। আপনি ImageLoader (Coil-এর জন্য) বা DownsampleStrategy
(Glide-এর জন্য) ব্যবহার করে
তাদের ডাউনস্যাম্পলিং স্ট্র্যাটেজি কনফিগার করতে পারবেন। আপনি ম্যানুয়ালি বিটম্যাপ ম্যানেজ করলে, ছোট ভার্সন ডিকোড করতে
inSampleSize ব্যবহার করতে পারবেন। এটি নিরাপদে করতে, আপনাকে প্রথমে
মেমরি বরাদ্দ না করে ছবির ডাইমেনশন পড়তে inJustDecodeBoundsকে true-এ সেট করতে হবে,
স্যাম্পেলের সাইজ গণনা করতে হবে, inSampleSizeকে সেই ভ্যালুতে সেট করতে হবে,
inJustDecodeBoundsকে false-এ সেট করতে হবে এবং তারপরে ছবিটি ডিকোড করতে হবে।
সার্ভার-সাইড রিসাইজিং বেছে নিন
সম্ভব হলে, আপনার ব্যাকএন্ড সার্ভার থেকে সরাসরি আপনার প্রয়োজনীয় সঠিক ছবির ডাইমেনশনের জন্য অনুরোধ করুন। এটি নেটওয়ার্কের ব্যবহার ও আপনার ডিস্ক ক্যাশে ফুটপ্রিন্ট কমায়, একই সাথে ডিভাইসে ছবির সাইজ পরিবর্তন করার মেমরি ওভারহেড এড়িয়ে গিয়ে মেমরির ব্যবহার কমায়।
আপনি লাইব্রেরি কনফিগার করতে পারেন যাতে টার্গেট ভিউ সাইজ ডায়নামিকভাবে ছবির URL-এ
যোগ করা যায়। যেমন, Coil কাস্টম ইন্টারসেপ্টর ব্যবহার করে এটি করার অনুমতি দেয় এবং Glide
কাস্টম মডেল লোডার (যেমন BaseGlideUrlLoader) ব্যবহার করে এটিতে সহায়তা করে।
আনকনস্ট্রেইন্ড লেআউট সাইজ এড়িয়ে চলুন
ইমেজ লোডার যাতে কার্যকরভাবে ডাউনস্যাম্পল (ক্লায়েন্ট-সাইড বা সার্ভার-সাইড) করতে পারে, তার জন্য অনুরোধ কার্যকর করার আগে টার্গেট সাইজ জানতে হবে।
wrapContentSize ব্যবহার করা বা রিমোট ইমেজ লোড করে এমন কম্পোজেবলে
ডাইমেনশন আনকনস্ট্রেনড রাখা এড়িয়ে চলুন। এইসব লাইব্রেরি টার্গেট বাউন্ড অনুমান করতে না পারলে, সেগুলি আসল ফুল-সাইজ ছবি লোড করার জন্য ফিরে আসে।
এর ফলে, প্রয়োজনের তুলনায় অনেক বড় ছবি লোড হতে পারে, যার ফলে মেমরির ব্যবহার ও লেটেন্সি বেড়ে যায়।
পরিবর্তে, আপনার ইমেজ কম্পোজেবলে নির্দিষ্ট ডাইমেনশন সেট করুন (যেমন, Modifier.size ব্যবহার করে) অথবা একটি অ্যাস্পেক্ট রেশিও নির্ধারণ করুন। এটি লেআউট ইঞ্জিনকে
সঠিক পিক্সেল টার্গেট আগে থেকেই গণনা করতে দেয়, যা ইমেজ লোডার তারপর
সঠিক আকারের অ্যাসেটের অনুরোধ করতে এবং ডিকোড করতে ব্যবহার করতে পারে।
বিভিন্ন স্ক্রিন সাইজের জন্য বিকল্প রিসোর্স প্রদান করুন
আপনি অ্যাপের সাথে ছবি শিপ করলে, বিভিন্ন ডিভাইসের রেজোলিউশনের জন্য বিভিন্ন সাইজের অ্যাসেট দেওয়ার কথা বিবেচনা করুন। এটি ডিভাইসে আপনার অ্যাপের ডাউনলোড সাইজ কমাতে এবং পারফর্ম্যান্স উন্নত করতে সাহায্য করতে পারে কারণ এটি কম রেজোলিউশনের ডিভাইসে কম রেজোলিউশনের ছবি লোড করবে। বিভিন্ন ডিভাইসের সাইজের জন্য বিকল্প বিটম্যাপ প্রদান করার বিষয়ে আরও তথ্যের জন্য, বিকল্প বিটম্যাপ ডকুমেন্টেশন চেক করুন।
সরাসরি প্যাডিং প্রয়োগ করবেন না
কখনও কখনও আপনাকে কোনও ছবিতে প্যাডিং যোগ করতে হতে পারে। যেমন, আপনি লেটারবক্সিংয়ের জন্য ছবির চারপাশে ট্রান্সপারেন্ট বর্ডার রাখতে চাইতে পারেন।
এইসব ক্ষেত্রে, ছবির ডাইমেনশন পরিবর্তন করে, সরাসরি ছবিতে প্যাডিং যোগ করবেন না। পরিবর্তে, ছবির ডাইমেনশন যেমন আছে তেমনই রাখুন,
এবং InsetDrawable ব্যবহার করে স্ক্রিনে ছবির লোকেশন অ্যাডজাস্ট করুন।
অন্যথায়, আপনি কম্পোজেবল বা ভিউতে প্যাডিং যোগ করতে পারেন যা
ছবি ধরে রাখে।
সঠিক পিক্সেল ফর্ম্যাট বেছে নিন
সঠিক পিক্সেল ফর্ম্যাট বেছে নিয়ে মেমরি ও কোয়ালিটির মধ্যে ব্যালেন্স করুন। RGB_565 ব্যবহার করুন
যখন আপনার স্বচ্ছতার প্রয়োজন হয় না; এই ফর্ম্যাটটি ডিফল্ট ARGB_8888 ফর্ম্যাটের অর্ধেক মেমরি ব্যবহার করে।
Glide-এ আপনি DecodeFormat ব্যবহার করে এটি কনফিগার করতে পারবেন। Coil-এ, আপনি
bitmapConfig প্রপার্টি ব্যবহার করতে পারবেন।
সম্ভব হলে ভেক্টর ব্যবহার করুন
জ্যামিতিক আকারের ছবিগুলির জন্য, ভেক্টর গ্রাফিক বিটম্যাপের চেয়ে অনেক ছোট এবং যেকোনও ডিসপ্লে ডেনসিটির জন্য মসৃণভাবে স্কেল করে। উপযুক্ত হলে, গ্রাফিক্স দেখানোর জন্য
ShapeDrawable-এর মতো এলিমেন্ট ব্যবহার করুন।
সম্ভব হলে বিটম্যাপ রিলিজ ও আবার ব্যবহার করুন
বড় গ্রাফিক ফাইল অনেক মেমরি ব্যবহার করতে পারে। তাদের প্রভাব কমাতে, আপনি যখনই পারবেন গ্রাফিক অবজেক্ট রিলিজ বা আবার ব্যবহার করা উচিত।
আপনি যদি কোনও ইমেজ লোডিং লাইব্রেরি ব্যবহার করেন, তাহলে আপনার আর প্রয়োজন না হলে লাইব্রেরির ম্যানেজ করা পুলে বিটম্যাপ রিলিজ করতে ভুলবেন না। প্রয়োজন হলে লাইব্রেরি অবজেক্ট আবার ব্যবহার করতে পারে এবং ভবিষ্যতের প্রয়োজনের জন্য মেমরি বাফার উপলভ্য রাখে।
আপনি যদি ম্যানুয়ালি গ্রাফিক্স ম্যানেজ করেন, তাহলে আপনার কাজ শেষ হয়ে গেলে
Bitmap.recycle কল করে বিটম্যাপ রিলিজ করা উচিত
এবং গার্বেজ কালেকশনের উপর নির্ভর করার পরিবর্তে
অবিলম্বে Bitmap রেফারেন্স বাতিল করা উচিত।
অন্যান্য পরামর্শ ও কৌশল
গ্রাফিক্স ম্যানেজ করার সময় আপনার অ্যাপের পারফর্ম্যান্স উন্নত করার জন্য এই বিভাগে আরও কিছু উপায় তালিকাভুক্ত করা হয়েছে।
আপনার AAB/APK ফাইলের সাথে বড় সাইজের ছবি প্যাকেজ করবেন না
অ্যাপ ডাউনলোড সাইজ বড় হওয়ার অন্যতম প্রধান কারণ হল AAB বা APK ফাইলের মধ্যে প্যাকেজ করা গ্রাফিক্স। প্রয়োজনের চেয়ে বড় সাইজের ছবির ফাইল প্যাকেজ করছেন কিনা তা নিশ্চিত করতে APK Analyzer টুল ব্যবহার করুন। সাইজ কমান অথবা ছবিগুলি কোনও সার্ভারে রাখার কথা বিবেচনা করুন এবং শুধুমাত্র প্রয়োজন হলে সেগুলি ডাউনলোড করুন।
অপ্রয়োজনীয় বিটম্যাপ খুঁজুন
আপনার কাছে একই ছবির একাধিক কপি থাকলে, তা মেমরি নষ্ট করে। আপনি Android Studio প্রোফাইলার ব্যবহার করে অপ্রয়োজনীয় গ্রাফিক্স শনাক্ত করতে পারবেন। হিপ ডাম্প ক্যাপচার করতে হিপ ডাম্প অ্যানালাইজার ব্যবহার করুন এবং ডুপ্লিকেট বিটম্যাপ সেটিং বেছে নিয়ে ফলাফল ফিল্টার করুন।
ImageBitmap ব্যবহার করার সময়, ড্র করার আগে prepareToDraw-কে কল করুন
ImageBitmap ব্যবহার করার সময়, GPU-তে টেক্সচার আপলোড করার প্রসেস শুরু করতে, আসলে এটি আঁকার আগে ImageBitmap#prepareToDraw() কল করুন। এটি
GPU-কে টেক্সচার প্রস্তুত করতে এবং স্ক্রিনে ভিজ্যুয়াল দেখানোর পারফর্ম্যান্স উন্নত করতে
সাহায্য করে। বেশিরভাগ ইমেজ লোডিং লাইব্রেরি ইতিমধ্যেই এই অপ্টিমাইজেশন করে, তবে
আপনি যদি নিজে ImageBitmap ক্লাস নিয়ে কাজ করেন, তাহলে এটি
মনে রাখতে হবে।
Painter-এর পরিবর্তে আপনার কম্পোজেবলে প্যারামিটার হিসেবে Int DrawableRes বা URL পাস করাকে অগ্রাধিকার দিন
ছবি নিয়ে কাজ করার জটিলতার কারণে (যেমন, Bitmaps-এর জন্য equals
ফাংশন লেখা কম্পিউটেশনের দিক থেকে ব্যয়বহুল হবে), Painter API-কে
স্পষ্টভাবে @Stable
অ্যানোটেশনের মাধ্যমে স্টেবল হিসেবে চিহ্নিত করা হয়নি। অস্থির ক্লাস অপ্রয়োজনীয় রিকম্পোজিশনের কারণ হতে পারে, কারণ
কম্পাইলার সহজে অনুমান করতে পারে না যে ডেটা পরিবর্তন হয়েছে কিনা।
তাই, আমরা সাজেস্ট করি যে প্যারামিটার হিসেবে Painter পাস করার পরিবর্তে
আপনার কম্পোজেবলে প্যারামিটার হিসেবে URL বা ড্রয়েবল রিসোর্স আইডি পাস করুন।
// Prefer this:
@Composable
fun MyImage(url: String) {
}
// Over this:
@Composable
fun MyImage(painter: Painter) {
}
আপনার জন্য সাজেস্ট করা হয়েছে
- মনে রাখবেন: জাভাস্ক্রিপ্ট বন্ধ থাকলে লিঙ্ক টেক্সট দেখানো হয়
- ImageBitmap বনাম ImageVector {:#bitmap-vs-vector}
- Compose-এ UI স্টেট সেভ করা
- Jetpack Compose-এর পর্যায়