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