মেমরি দক্ষতাকে অগ্রাধিকার দেওয়া: অ্যান্ড্রয়েড ১৭-এর জন্য অপরিহার্য পদক্ষেপ
১০ মিনিটের পাঠ
যদিও অ্যাপের পারফরম্যান্স বলতে প্রায়শই একটি মসৃণ UI এবং দ্রুত চালু হওয়াকে বোঝানো হয়, মেমোরিই হলো সেই নীরব ভিত্তি যার উপর এই দৃশ্যমান মেট্রিকগুলো নির্মিত হয়। এটা কোনো গোপন বিষয় নয় যে আমরা এমন একটি পরিবর্তন দেখতে পাচ্ছি যেখানে ডিভাইসের মেমোরি আগের চেয়ে অনেক বেশি গুরুত্বপূর্ণ হয়ে উঠেছে। আমরা শুধু Android 17-এর মাধ্যমে অ্যান্ড্রয়েড মেমোরি অপটিমাইজেশনে অগ্রগতিই করিনি, বরং এই বছরের শেষের দিকে আরও কঠোর মেমোরির প্রয়োজনীয়তা পূরণে আপনাকে সাহায্য করার জন্য প্রয়োজনীয় টুলিং এবং API সাপোর্টও প্রদান করছি।
ডিভাইসের স্থিতিশীলতা নিশ্চিত করতে, অ্যান্ড্রয়েড ১৭ থেকে সিস্টেম ডিভাইসের মোট র্যামের উপর ভিত্তি করে অ্যাপের মেমরি সীমা প্রয়োগ করা শুরু করবে। যদি কোনো অ্যাপ সেই সীমা অতিক্রম করে, তাহলে অ্যান্ড্রয়েড কোনো স্ট্যাক ট্রেস ছাড়াই প্রসেসটি বন্ধ করে দেবে।
এইসব জোরপূর্বক বন্ধ হয়ে যাওয়া ছাড়াও, অপটিমাইজ না করা মেমোরি ব্যবহার অনিবার্যভাবে ব্যবহারকারীর অভিজ্ঞতাকে খারাপ করে দেয়। যখন অ্যাপটি হিপ মেমোরির সীমার কাছাকাছি চলে আসে, তখন এটি ঘন ঘন গার্বেজ কালেকশন চালু করে—যার ফলে UI-তে লক্ষণীয়ভাবে আটকে যাওয়া বা থেমে থেমে চলার মতো সমস্যা দেখা দেয়। এছাড়াও, যখন কোনো ডিভাইসে উপলব্ধ মেমোরি শেষ হয়ে যায়, তখন সিস্টেম পেজগুলো পুনরুদ্ধার করার জন্য তাড়াহুড়ো করে, যার ফলে সিপিইউ-এর উপর চাপ পড়ে, UI-তে বিলম্ব হয় এবং ব্যাটারি দ্রুত শেষ হয়ে যায়। যদি মেমোরির ঘাটতি খুব বেশি হয়, তবে এটি লো মেমোরি কিলার (LMK) ইভেন্টের কারণ হতে পারে, যা হঠাৎ করে ব্যাকগ্রাউন্ড প্রসেসগুলো বন্ধ করে দেয় এবং অ্যাপগুলোকে ধীরগতির কোল্ড স্টার্টের দিকে ঠেলে দেয় ও ব্যবহারকারীর স্টেট হারিয়ে ফেলে।
উচ্চ পারফরম্যান্স সম্পন্ন অ্যাপ তৈরি করতে এবং এই ধরনের বাধ্যতামূলক সমাপ্তি এড়াতে, আমরা আপনাকে নিম্নলিখিত মেমরি অপ্টিমাইজেশন কৌশলগুলি গ্রহণ করার পরামর্শ দিচ্ছি:
- R8 দিয়ে বাইটকোড অপ্টিমাইজেশন সর্বোচ্চ করুন
- ইমেজ লোডিং অপ্টিমাইজ করুন
- অ্যান্ড্রয়েড স্টুডিও দিয়ে মেমরি লিক শনাক্ত ও সমাধান করুন
- অ্যাপটি দৃশ্যমান অবস্থা থেকে বেরিয়ে গেলে মেমরি ছাঁটাই করুন।
- প্রোফাইলিংম্যানেজারের মাধ্যমে উন্নত মেমরি পর্যবেক্ষণযোগ্যতা
এই ব্লগ পোস্টটির একটি সংক্ষিপ্ত সংস্করণ ভিডিও আকারেও পাওয়া যাচ্ছে, দেখে নিন!
অ্যান্ড্রয়েড ১৭ অ্যাপের মেমরি সীমা বোঝা
অ্যান্ড্রয়েড ১৭-এ অ্যাপ মেমরি লিমিট চালু করা হচ্ছে, যাতে কোনো একজন দুষ্কৃতকারী ব্যবহারকারীর মাল্টিটাস্কিং অভিজ্ঞতা এবং পুরো ডিভাইসের স্থিতিশীলতা নষ্ট করতে না পারে।
এই স্থাপত্যগত পরিবর্তনের কারণগুলো নিচে তুলে ধরা হলো:
- ক্রমিক কিল প্রতিরোধ : যখন কোনো অ্যাপ বিশেষ সুবিধাপ্রাপ্ত অবস্থায় (যেমন, এটি একটি ফোরগ্রাউন্ড সার্ভিস চালাচ্ছে) থাকার সময় আকারে বড় হয়ে যায় বা মেমোরি লিক করে, তখন এটি প্রাথমিকভাবে সিস্টেমের লো মেমোরি কিলার (LMK) থেকে সুরক্ষিত থাকে। যখন এই একটিমাত্র অ্যাপ অনিয়ন্ত্রিতভাবে বাড়তে থাকে এবং র্যাম দখল করতে থাকে, তখন LMK এই মেমোরি দখলকারী অ্যাপটির জন্য জায়গা পুনরুদ্ধার করতে বাধ্য হয়ে কয়েক ডজন ছোট, সুশৃঙ্খল ক্যাশড অ্যাপ এবং ব্যাকগ্রাউন্ড জব বন্ধ করে দেয়।
- মাল্টিটাস্কিং এবং ব্যবহারকারীর অবস্থা সংরক্ষণ: যখন একটিমাত্র মেমরি লিকিং প্রসেসের জন্য সিস্টেমকে ক্যাশ করা অ্যাপগুলো মুছে ফেলতে বাধ্য করা হয়, তখন মাল্টিটাস্কিং-এর অভিজ্ঞতা মারাত্মকভাবে খারাপ হয়ে যায়। ব্যবহারকারীরা আগের ক্যাশ করা অ্যাপ্লিকেশনগুলোতে ফিরে এলে প্রায়-তাৎক্ষণিক ওয়ার্ম রেজিউমের পরিবর্তে ধীরগতির কোল্ড স্টার্টের সম্মুখীন হন। এই অদক্ষতা সিপিইউ-এর উপর আরও বেশি চাপ সৃষ্টি করে এবং ব্যাটারির ব্যবহার দ্রুত শেষ করে। এটি সম্প্রতি ব্যবহৃত অ্যাপগুলোতে ব্যবহারকারীর কনটেক্সট, যেমন—স্ক্রোল পজিশন, নেভিগেশন স্ট্যাক এবং ইন-গেম প্রগ্রেসও নষ্ট করে দিতে পারে।
ফিল্ডে এই সীমাবদ্ধতাগুলোর কারণে আপনার অ্যাপ সেশন প্রভাবিত হয়েছে কিনা তা জানতে, আপনি ApplicationExitInfo-এর মধ্যে getDescription() কল করতে পারেন। যদি সিস্টেম কোনো সীমা প্রয়োগ করে থাকে, তাহলে এক্সিট কারণ হিসেবে REASON_OTHER রিপোর্ট করা হয় এবং ডেসক্রিপশন স্ট্রিং-এ "MemoryLimiter:AnonSwap" লেখা থাকবে। মেমরি লিমিটে পৌঁছালে স্বয়ংক্রিয়ভাবে হিপ ডাম্প ক্যাপচার করার জন্য আপনি TRIGGER_TYPE_ANOMALY ব্যবহার করে ট্রিগার-ভিত্তিক প্রোফাইলিং-এর সুবিধাও নিতে পারেন। এছাড়াও, অ্যান্ড্রয়েড গুগল প্লে কনসোলের মধ্যে ডেভেলপারদের জন্য ফিল্ডের আরও মেমরি মেট্রিক্স তুলে ধরতে সক্রিয়ভাবে কাজ করছে।
আমরা আমাদের মেমরি লিমিট সংক্রান্ত ডকুমেন্টেশনকে আরও প্রসারিত করেছি এবং এতে লোকাল ডিবাগিং কমান্ড অন্তর্ভুক্ত করেছি। এর ফলে আপনি আপনার লোকাল এনভায়রনমেন্টে মেমরির সীমাবদ্ধতা অনুকরণ করতে এবং যেকোনো মেমরি লিমিট প্রয়োগের অধীনে আপনার অ্যাপ্লিকেশনের আচরণ যাচাই করতে পারবেন।
R8 দিয়ে বাইটকোড অপ্টিমাইজেশন সর্বোচ্চ করুন
আপনার অ্যাপের মেমরি ফুটপ্রিন্ট কমানোর একটি অত্যন্ত কার্যকর উপায় হলো R8 অপটিমাইজারটি সক্রিয় করা। ক্লাস, মেথড এবং ফিল্ডগুলোকে ছোট নামে রূপান্তর করে এবং অব্যবহৃত কোড ও রিসোর্স বাদ দিয়ে, R8 এক্সিকিউশনের সময় প্রয়োজনীয় রেসিডেন্ট কোডের পরিমাণ কমিয়ে আপনার অ্যাপের মেমরি ফুটপ্রিন্ট উল্লেখযোগ্যভাবে হ্রাস করে।
R8 রেসিডেন্ট কোড কমিয়ে আনে, যা মেমরি ফুটপ্রিন্ট সংকুচিত করে এবং LMK টার্মিনেশনের ঝুঁকি হ্রাস করে। এর ফলে ধীরগতির কোল্ড স্টার্টের পরিবর্তে ওয়ার্ম স্টার্ট বেশি ঘন ঘন হয়। এছাড়াও, সুবিন্যস্ত বাইটকোড মেইন-থ্রেডের সিপিইউ ওভারহেড কমায়, যা সরাসরি ANR রেট হ্রাস করে এবং ব্যবহারকারীকে আরও সাবলীল অভিজ্ঞতা প্রদান করে। উদাহরণস্বরূপ, ডিজিটাল ব্যাংক মনজো সম্পূর্ণ R8 অপটিমাইজেশন চালু করার পর তাদের ANR রেট ৩৫% হ্রাস, কোল্ড স্টার্ট রেট ৩০% বৃদ্ধি এবং অ্যাপের সামগ্রিক আকার ৯% হ্রাস পেয়েছে।

আপনার build.gradle ফাইলে R8 সঠিকভাবে কনফিগার করতে:
-
isShrinkResources = trueএবংisMinifyEnabled = trueসেট করুন। - পুরোনো proguard-
proguard-android.txtproguard-android-optimize.txtব্যবহার করুন, কারণ পুরোনো ফাইলটি অপটিমাইজেশন প্রতিরোধ করে এবং অ্যান্ড্রয়েড গ্রেডল প্লাগইন ৯-এ এটি আর সমর্থিত নয়। - আপনার
gradle.propertiesথেকেandroid.enableR8.fullMode = falseসরিয়ে ফেলুন।
আপনি যদি আপনার কোডবেসে রিফ্লেকশন ব্যবহার করে থাকেন, তাহলে কোডের সেই অংশগুলোকে R8-এর অপটিমাইজেশন থেকে বিরত রাখতে Keep রুল যোগ করুন। সর্বোচ্চ অপটিমাইজেশন পেতে Keep রুলগুলোর পরিধি সংকীর্ণ রাখতে ভুলবেন না।
সর্বোত্তম অপ্টিমাইজেশন পেতে, আপনার কিপ রুল ফাইলে এই সেরা অনুশীলনগুলো অনুসরণ করা নিশ্চিত করুন।
-
-dontoptimize,-dontshrink, এবং-dontobfuscateএর মতো গ্লোবাল অপশনগুলো সরিয়ে ফেলুন, যেগুলো R8-কে সম্পূর্ণ কোডবেস অপ্টিমাইজ করতে বাধা দেয়। - Activity, Services, Views বা Broadcast receivers-এর মতো Android কম্পোনেন্টগুলোকে অপ্টিমাইজ করতে বাধা দেয় এমন নিয়মগুলো সরিয়ে ফেলুন।
- শুধুমাত্র নির্দিষ্ট ক্লাস বা মেথডগুলোকে লক্ষ্য করার জন্য প্যাকেজ জুড়ে থাকা ব্যাপক 'কিপ' নিয়মগুলোকে পরিমার্জন করুন।
আরও সেরা অনুশীলন দেখতে, আমাদের 'কিপ রুলস' ডকুমেন্টেশন দেখুন।
লাইব্রেরি ডেভেলপার R8 সেরা অনুশীলন
আপনি যদি একজন লাইব্রেরি ডেভেলপার হন, তবে আপনার ব্যবহারকারীদের প্রয়োজনীয় নিয়মগুলো কঠোরভাবে আপনার consumer-rules file রাখুন এবং আপনার লাইব্রেরির অভ্যন্তরীণ সুরক্ষা নিয়মগুলো আপনার proguard-rules.pro ফাইলে রাখুন। লাইব্রেরি অপ্টিমাইজ করার পদ্ধতি সম্পর্কে আরও তথ্যের জন্য, লাইব্রেরি লেখকদের জন্য অপ্টিমাইজেশন দেখুন।
R8 কনফিগারেশন অ্যানালাইজার
আপনার R8 অপ্টিমাইজেশন নিরীক্ষা করতে, কনফিগারেশন অ্যানালাইজার ব্যবহার করুন। কনফিগারেশন অ্যানালাইজার অপ্টিমাইজেশনের বর্তমান অবস্থা দেখায় অস্পষ্টকরণ, অপ্টিমাইজেশন এবং সঙ্কুচিতকরণ স্কোর। কনফিগারেশন অ্যানালাইজারের সাহায্যে, আপনি এটাও বুঝতে পারবেন যে প্রতিটি 'কিপ' রুলের কারণে কতগুলো ক্লাস, মেথড বা ফিল্ড অপ্টিমাইজেশন থেকে বঞ্চিত হচ্ছে। সর্বোচ্চ অপ্টিমাইজেশন নিশ্চিত করতে এই বিস্তৃত প্যাকেজ-ব্যাপী 'কিপ' রুলগুলোকে পরিমার্জন করুন।
কনফিগারেশন অ্যানালাইজার ব্যবহার করে, আপনি এমন কিপ রুলগুলোও শনাক্ত করতে পারেন যেগুলো অন্য কিপ রুলকে অন্তর্ভুক্ত করছে, অপ্রয়োজনীয় কিপ রুল এবং অব্যবহৃত কিপ রুল।

R8 এজেন্ট দক্ষতা
আপনি ভুল কনফিগারেশন সমাধান করতে এবং আপনার নিয়মগুলোকে পরিমার্জন করে অ্যাপের পারফরম্যান্স উন্নত করার জন্য অ্যান্ড্রয়েড স্টুডিও এজেন্ট বা অন্যান্য এআই টুলের সাথে R8 এজেন্ট স্কিলটিও ব্যবহার করতে পারেন। (এআই-চালিত স্কিল থেকে প্রাপ্ত তথ্যের জন্য প্রযুক্তিগত যাচাইকরণের প্রয়োজন হবে)
ইমেজ লোডিং অপ্টিমাইজ করুন
বিটম্যাপগুলো সাধারণত আপনার অ্যাপের মেমরিতে থাকা সবচেয়ে বড় এবং সাধারণ অবজেক্ট। এগুলো ইমেজ লোডিং প্রক্রিয়ার চূড়ান্ত পর্যায়কে নির্দেশ করে, যেখানে JPEG বা PNG-এর মতো কম্প্রেসড ফাইলগুলোকে প্রদর্শনের জন্য ডিকোড করে র পিক্সেল ডেটাতে পরিণত করা হয়। এর মানে হলো, একটি ছোট্ট ১০০ কিলোবাইটের কম্প্রেসড ইমেজও ফুলেফেঁপে কয়েক মেগাবাইট র্যাম দখল করতে পারে, কারণ মেমরি খরচ ইমেজের পিক্সেল ডাইমেনশন এবং কালার ডেপথ দ্বারা নির্ধারিত হয়। যেহেতু ফ্রেম আঁকার জন্য বিটম্যাপ অপারেশনগুলো প্রায়শই একটি গুরুত্বপূর্ণ অংশ, তাই অপটিমাইজ না করা ইমেজগুলো মারাত্মক মেমরি স্ফীতি এবং UI জ্যাঙ্কের কারণ হয়।
গুগল কোটলিন-ভিত্তিক প্রোজেক্টের জন্য, বিশেষ করে জেটপ্যাক কম্পোজ দিয়ে ডেভেলপ করার সময়, কয়েল (Coil) এবং জাভা-ভিত্তিক অ্যাপ্লিকেশনের জন্য গ্লাইড (Glide) ইমেজ লোডিং লাইব্রেরি ব্যবহারের পরামর্শ দেয়।
এই পাঁচটি সর্বোত্তম অনুশীলন গ্রহণ করুন
- ইমেজ ডাউনস্যাম্পল করুন: আপনি যদি ম্যানুয়ালি বিটম্যাপ লোড করেন, তবে একটি বিশাল ইমেজকে ছোট থাম্বনেইল ভিউতে লোড করা থেকে বিরত থাকুন; এর একটি ছোট সংস্করণ লোড করতে inSampleSize ব্যবহার করুন। Glide এবং Coil ডিফল্টরূপে ইমেজ ডাউনস্যাম্পল করে এবং আপনি যথাক্রমে DownsampleStrategy এবং ImageLoader ব্যবহার করে এই ডাউনস্যাম্পল কৌশলটি কনফিগার করতে পারেন।
- ক্রপিং: লেটারবক্সিংয়ের উদ্দেশ্যে (যেমন, ছবির আকার বড় করার জন্য একটি স্বচ্ছ বর্ডার তৈরি করতে) সরাসরি কোনো ইমেজ ফাইলে প্যাডিং যুক্ত করা থেকে বিরত থাকুন। এই বর্ডারগুলোকে স্থায়ীভাবে যুক্ত না করে, InsetDrawable ব্যবহার করুন অথবা বিটম্যাপ ধারণকারী View বা Composable-এর মধ্যেই সরাসরি প্যাডিং প্রয়োগ করুন।
- কনফিগারেশন: সঠিক পিক্সেল ফরম্যাট বেছে নিয়ে মেমরি এবং কোয়ালিটির মধ্যে ভারসাম্য বজায় রাখুন। যখন স্বচ্ছতার প্রয়োজন হয় না, তখন
RGB_565ব্যবহার করুন, যা ডিফল্টARGB_8888ফরম্যাটের অর্ধেক মেমরি ব্যবহার করে। Glide-এ আপনি DecodeFormat ব্যবহার করে এবং Coil-এ bitmapConfig প্রপার্টি ব্যবহার করে এটি কনফিগার করতে পারেন। - ভেক্টর ড্রয়েবলকে অগ্রাধিকার দিন: সাধারণ জ্যামিতিক অ্যাসেটের জন্য, রাস্টারাইজড বিটম্যাপ ডিকোড করার একটি হালকা বিকল্প হিসেবে ShapeDrawable ব্যবহার করুন। XML-এর মাধ্যমে এই অ্যাসেটগুলোকে একবার সংজ্ঞায়িত করার ফলে, আপনি নিশ্চিত করতে পারেন যে এগুলো সমস্ত ডিসপ্লে ডেনসিটিতে নির্বিঘ্নে স্কেল করবে এবং একই সাথে রিসোর্স-জনিত মেমরি ব্লট কার্যকরভাবে দূর করবে।
- পুনর্ব্যবহার: যদি আপনার অ্যাপ্লিকেশন বিটম্যাপ ম্যানুয়ালি পরিচালনা করে, তাহলে মেমরির ব্যবহার কমাতে, যখন কোনো বিটম্যাপের আর প্রয়োজন হবে না, তখন অ্যাপটির উচিত
bitmap.recycle()কল করা এবং সাথে সাথেBitmapরেফারেন্সটি বাতিল করে দেওয়া। আপনি যদি Glide বা Coil-এর মতো কোনো ইমেজ লোডিং লাইব্রেরি ব্যবহার করেন, তাহলে বিটম্যাপটিকে লাইব্রেরির ম্যানেজড পুলে ফেরত দিন। ভবিষ্যতের মেমরির প্রয়োজনের জন্য একটি বিদ্যমান বাফার সরবরাহ করার মাধ্যমে, পুলটি কার্যকরভাবে নতুন অ্যালোকেশনের অতিরিক্ত কাজ এড়িয়ে যায়।
আরও জানতে ইমেজের পারফরম্যান্স অপ্টিমাইজ করার বিষয়ে আমাদের ডকুমেন্টেশন দেখুন।
অ্যান্ড্রয়েড স্টুডিও টুলিং
আপনি অ্যান্ড্রয়েড স্টুডিও নারওয়াল ৪ ব্যবহার করে অপ্রয়োজনীয় বিটম্যাপগুলোও বাদ দিতে পারেন। নিচে পাঁচটি সহজ ধাপে সেগুলো খুঁজে বের করার পদ্ধতি দেওয়া হলো:
- অ্যান্ড্রয়েড স্টুডিওতে প্রোফাইলার ট্যাবটি খুলুন।
- আপনার অ্যাপের বর্তমান মেমরি অবস্থার একটি স্ন্যাপশট নিতে হিপ ডাম্প (বা "মেমরি ব্যবহার বিশ্লেষণ")-এ ক্লিক করুন এবং রেকর্ড চাপুন।
- অ্যানালাইসিসের ফলাফলে হলুদ সতর্কীকরণ ত্রিভুজ ⚠️-টি খুঁজুন, যা অ্যান্ড্রয়েড স্টুডিও একাধিকবার সংরক্ষিত ডুপ্লিকেট বিটম্যাপ চিহ্নিত করতে ব্যবহার করে। বিকল্পভাবে, প্রোফাইলার হেডারে গিয়ে "Filter by:" নির্বাচন করুন এবং "Duplicate Bitmaps" সেটিংটি বেছে নিন।
- যেকোনো চিহ্নিত এন্ট্রিতে ক্লিক করলে বিটম্যাপ প্রিভিউ প্যানটি খুলবে, যার মাধ্যমে আপনি স্পষ্টভাবে দেখতে পারবেন কোন ছবিটি বারবার একই সমস্যা করছে।
- আপনার কোডের অপ্রয়োজনীয় লোডিং লজিক খুঁজে বের করতে এবং আরও ভালো ক্যাশিং কৌশল প্রয়োগ করতে সেই ভিজ্যুয়াল কনফার্মেশনটি ব্যবহার করুন।

অ্যান্ড্রয়েড স্টুডিও দিয়ে মেমরি লিক শনাক্ত ও সমাধান করুন
অ্যান্ড্রয়েডে মেমরি লিক তখন ঘটে, যখন আপনার কোড কোনো অবজেক্টের লাইফসাইকেল শেষ হওয়ার অনেক পরেও সেটির রেফারেন্স ধরে রাখে। এর ফলে গার্বেজ কালেক্টর (GC) সেই মেমরি পুনরুদ্ধার করতে পারে না, যা শেষ পর্যন্ত ধীরগতির পারফরম্যান্স বা OutOfMemoryError (OOM)-এর কারণ হয়।
অ্যান্ড্রয়েড স্টুডিও পান্ডা ৩-এ একটি বিশেষ LeakCanary প্রোফাইলার টাস্ক রয়েছে, যা ডেভেলপারদের সরাসরি IDE-এর মধ্যেই রিয়েল-টাইম মেমরি লিক বিশ্লেষণ করতে এবং ট্রেস ম্যাপ করতে সাহায্য করে।
অ্যান্ড্রয়েড স্টুডিও-এর LeakCanary প্রোফাইলার টাস্কটি সক্রিয়ভাবে মেমরি লিক বিশ্লেষণের কাজটি আপনার ডিভাইস থেকে আপনার ডেভেলপমেন্ট মেশিনে স্থানান্তর করে, যার ফলে ডিভাইসে লিক বিশ্লেষণের তুলনায় বিশ্লেষণ পর্যায়ে পারফরম্যান্সে উল্লেখযোগ্য উন্নতি ঘটে।

এছাড়াও, মেমরি লিক বিশ্লেষণ এখন IDE-এর মধ্যেই প্রাসঙ্গিক করা হয়েছে এবং আপনার সোর্স কোডের সাথে সম্পূর্ণরূপে সমন্বিত করা হয়েছে। এটি ‘গো টু ডিক্লারেশন’ এবং অন্যান্য সহায়ক কোড সংযোগের মতো বৈশিষ্ট্য প্রদান করে, যা মেমরি লিক তদন্ত ও সমাধান করার জন্য প্রয়োজনীয় জটিলতা এবং সময়কে ব্যাপকভাবে হ্রাস করে।
সাধারণ মেমোরি লিকের উদাহরণ
যখন কোনো অবজেক্ট তার নির্ধারিত জীবনকালের পরেও মেমরিতে থেকে যায়, তখন মেমরি লিক ঘটে। এটি সাধারণত নিম্নলিখিত কারণে হয়ে থাকে:
- যেসব ফ্র্যাগমেন্ট, অ্যাক্টিভিটি বা ভিউ আর ব্যবহার করা হয় না, সেগুলোর রেফারেন্স ধরে রাখা।
- প্রসঙ্গ উল্লেখের অব্যবস্থাপনা।
- অবজারভার, লিসেনার এবং রিসিভারদের যথাযথভাবে অনিবন্ধিত করতে ব্যর্থ হওয়া।
- যেসব কম্পোনেন্টের লাইফসাইকেল কম, সেগুলোর সাথে আবদ্ধ অবজেক্টের স্ট্যাটিক রেফারেন্স তৈরি করা।
এখানে কয়েকটি উদাহরণমূলক পরিস্থিতি দেওয়া হলো:
| দৃশ্যকল্প | কম্পোজ-ভিত্তিক উদাহরণ | দৃশ্য-ভিত্তিক উদাহরণ |
| প্রসঙ্গ ফাঁস | উদাহরণ: সমাধান: | উদাহরণ: সমাধান: |
| লিকিং লিসেনার্স | উদাহরণ: সমাধান: | উদাহরণ: সমাধান: |
| লিকিং ভিউস | উদাহরণ:
| উদাহরণ: সমাধান: |
অ্যাপটি দৃশ্যমান অবস্থা থেকে বেরিয়ে গেলে মেমরি ছাঁটাই করুন।
মেমরি ম্যানেজমেন্টের ওভারভিউ- তে যেমন ব্যাখ্যা করা হয়েছে, অ্যান্ড্রয়েড গুরুত্বপূর্ণ কাজের জন্য মেমরি খালি করতে প্রয়োজনে আপনার অ্যাপ থেকে মেমরি পুনরুদ্ধার করতে পারে বা আপনার অ্যাপটি সম্পূর্ণরূপে বন্ধ করে দিতে পারে। অ্যান্ড্রয়েড সাধারণত আপনার অ্যাপ থেকে মেমরি পুনরুদ্ধার করে যখন এটি ব্যবহারকারীর কাছে দৃশ্যমান থাকে না, যেমন মেমরিতে থাকা আপনার অ্যাপের কিছু কোড এবং ডেটা পেজ বাতিল করে বা আপনার হিপ অ্যালোকেশন সংকুচিত করে। যখন ব্যবহারকারী আপনার অ্যাপটি পুনরায় চালু করে এবং আপনার অ্যাপ পুনরুদ্ধার করা কোনো মেমরি অ্যাক্সেস করার চেষ্টা করে, তখন অপারেটিং সিস্টেম চাহিদা অনুযায়ী সেই মেমরিটি পুনরায় সোয়াপ করে ফিরিয়ে আনে। এই সোয়াপিং প্রক্রিয়াটি ধীর হতে পারে এবং আপনার অ্যাপে অপ্রত্যাশিত ঝাঁকুনি বা আটকে যাওয়ার কারণ হতে পারে।
আপনার অ্যাপ থেকে কী পরিমাণ মেমরি পুনরুদ্ধার করা হবে, সেই সিদ্ধান্ত যদি আপনি অপারেটিং সিস্টেমের (OS) উপর ছেড়ে দেন, তাহলে আপনি দেখতে পারেন যে অ্যাপটি পুনরায় চালু করার কিছুক্ষণ পরেই OS এমন মেমরি পুনরুদ্ধার করে ফেলেছে যা আপনার প্রয়োজন হবে। এর পরিবর্তে, আপনার অ্যাপ স্বেচ্ছায় মেমরি বরাদ্দ বাতিল করতে পারে, যা এটি পরে প্রয়োজন অনুযায়ী এবং কম খরচে পুনরায় তৈরি করতে পারে। এটি করার জন্য, আপনি ComponentCallbacks2 ইন্টারফেসটি ইমপ্লিমেন্ট করতে পারেন। আপনি আপনার Activity , Fragment , Service , বা এমনকি আপনার নিজস্ব Application ক্লাসেও onTrimMemory ইমপ্লিমেন্ট করতে পারেন। গ্লোবাল ক্যাশ ম্যানেজমেন্টের জন্য Application ক্লাসে এর ব্যবহার অত্যন্ত কার্যকর।
প্রদত্ত onTrimMemory() কলব্যাক মেথডটি আপনার অ্যাপকে লাইফসাইকেল বা মেমরি-সম্পর্কিত ইভেন্টগুলো সম্পর্কে অবহিত করে, যা আপনার অ্যাপের জন্য স্বেচ্ছায় মেমরি ব্যবহার কমানোর একটি ভালো সুযোগ তৈরি করে।
মেমরি লাইফসাইকেল ম্যানেজমেন্টের ক্ষেত্রে, আপনার ইমপ্লিমেন্টেশনে শুধুমাত্র TRIM_MEMORY_UI_HIDDEN এবং TRIM_MEMORY_BACKGROUND এর উপরই মনোযোগ দেওয়া উচিত। অ্যান্ড্রয়েড ১৪ থেকে, সিস্টেম অন্যান্য লিগ্যাসি কনস্ট্যান্টের জন্য নোটিফিকেশন দেওয়া বন্ধ করে দিয়েছে, যেগুলোকে অ্যান্ড্রয়েড ১৫-এ আনুষ্ঠানিকভাবে ডেপ্রিকেটেড করা হয়েছিল।
TRIM_MEMORY_UI_HIDDEN : এই সিগন্যালটি নির্দেশ করে যে আপনার অ্যাপ্লিকেশনের ইউজার ইন্টারফেস (UI) ব্যবহারকারীর দৃষ্টির বাইরে চলে গেছে। এটি ইন্টারফেসের সাথে কঠোরভাবে যুক্ত থাকা উল্লেখযোগ্য মেমরি বরাদ্দ—যেমন বিটম্যাপ, ভিডিও প্লেব্যাক বাফার, বা জটিল অ্যানিমেশন রিসোর্স—মুক্ত করার একটি সুযোগ প্রদান করে।
TRIM_MEMORY_BACKGROUND : এই পর্যায়ে, আপনার প্রসেসটি ব্যাকগ্রাউন্ডে অবস্থান করছে এবং সিস্টেমের সার্বিক মেমরির চাহিদা মেটাতে এটিকে বন্ধ করে দেওয়ার কথা ভাবা হচ্ছে। আপনার প্রসেসটি ক্যাশড অবস্থায় কতক্ষণ থাকবে তার সময়কাল বাড়াতে এবং অ্যাপ কোল্ড স্টার্টের সংখ্যা কমাতে, ব্যবহারকারী তার সেশন পুনরায় শুরু করার পর যে রিসোর্সগুলো সহজেই পুনর্গঠন করা যায়, সেগুলো দ্রুত রিলিজ করে দেওয়া উচিত।
import android.content.ComponentCallbacks2 // Other import statements. class MainActivity : AppCompatActivity(), ComponentCallbacks2 { /** * Release memory when the UI becomes hidden or when system resources become low. * @param level the memory-related event that is raised. */ override fun onTrimMemory(level: Int) { if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { // Release memory related to UI elements, such as bitmap caches. } if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) { // Release memory related to background processing, such as by // closing a database connection. } } }
দ্রষ্টব্য: onTrimMemory ইন্টিগ্রেশনটি SDK সাপোর্টের উপর নির্ভর করতে পারে। উদাহরণস্বরূপ, কিছু গেম এই সক্ষমতাটি চালু করার জন্য তাদের গেম ইঞ্জিনের উপর নির্ভর করে। অনুগ্রহ করে গেম মেমোরি অপটিমাইজেশন ডকুমেন্টগুলো দেখে নিন।
প্রোফাইলিংম্যানেজারের মাধ্যমে উন্নত মেমরি পর্যবেক্ষণযোগ্যতা
ফিল্ডে এমন মেমরি সমস্যা শনাক্ত ও নির্ণয় করতে, যা স্থানীয়ভাবে পুনরুৎপাদন করা যায় না, আপনার ProfilingManager API ব্যবহার করা উচিত। Android 15-এ প্রবর্তিত এই উন্নত অবজার্ভেবিলিটি API আপনাকে প্রোগ্রাম্যাটিকভাবে প্রকৃত ব্যবহারকারীদের Perfetto প্রোফাইল সংগ্রহ করার সুযোগ দেয়।
যেসব টিমের পারফরম্যান্স আর্টিফ্যাক্ট পরিচালনা ও হোস্ট করার জন্য নিজস্ব পরিকাঠামো নেই, তাদের এই কর্মপ্রবাহকে সুবিন্যস্ত করতে ক্র্যাশলিটিক্স একটি বিশেষায়িত সমাধান নিয়ে কাজ করছে। তারা ডেভেলপারদের মতামত জানানোর জন্য আমন্ত্রণ জানাচ্ছে।
অ্যান্ড্রয়েড ১৭ নতুন ইভেন্ট-চালিত ট্রিগার চালু করেছে , যার মধ্যে সবচেয়ে উল্লেখযোগ্য হলো TRIGGER_TYPE_OOM এবং TRIGGER_TYPE_ANOMALY ।
- OutOfMemoryError ক্র্যাশ ঘটার ঠিক মুহূর্তে OOM ট্রিগারটি স্বয়ংক্রিয়ভাবে একটি জাভা হিপ ডাম্প সংগ্রহ করে, যা অ্যালোকেশনের সঠিক অবস্থা প্রদান করে। সংগৃহীত OOM প্রোফাইলটি পরবর্তীবার অ্যাপটি চালু হওয়ার সময় সরবরাহ করা হয় এবং
registerForAllProfilingResultsকলব্যাকটি রেজিস্টার করে। - অ্যানোমালি ট্রিগারটি অতিরিক্ত বাইন্ডার স্প্যাম বা মেমরি থ্রেশহোল্ড লঙ্ঘনের মতো গুরুতর পারফরম্যান্স সমস্যা শনাক্ত করে। সিস্টেম অ্যাপটি বন্ধ করে দেওয়ার ঠিক আগে এই মেমরি অ্যানোমালি একটি হিপ ডাম্প প্রদান করে।
val profilingManager = applicationContext.getSystemService(ProfilingManager::class.java) val triggers = ArrayList<ProfilingTrigger>() triggers.add(ProfilingTrigger.Builder( ProfilingTrigger.TRIGGER_TYPE_ANOMALY)) val mainExecutor: Executor = Executors.newSingleThreadExecutor() val resultCallback = Consumer<ProfilingResult> { profilingResult -> if (profilingResult.errorCode != ProfilingResult.ERROR_NONE) { // upload profile result to server for further analysis setupProfileUploadWorker(profilingResult.resultFilePath) } profilingManager.registerForAllProfilingResults(mainExecutor, resultCallback) profilingManager.addProfilingTriggers(triggers)
একবার হিপ ডাম্প সংগ্রহ করার পর, আপনি সার্ভার থেকে প্রোফাইলটি ডাউনলোড করতে পারেন, অথবা স্থানীয়ভাবে adb pull কমান্ডের মাধ্যমে ফাইলটি Perfetto UI- তে ড্র্যাগ অ্যান্ড ড্রপ করতে পারেন। আপনার মেমরি ডিবাগিং ওয়ার্কফ্লোকে আরও সহজ করতে, হিপ ডাম্প এক্সপ্লোরার ব্যবহার করুন; এটি Perfetto UI-তে হিপ ডাম্পের জন্য নতুন ডিফল্ট ভিউ। এই টুলটি জাভা হিপ ডাম্প পরীক্ষা করার জন্য একটি সহজবোধ্য ইন্টারফেস প্রদান করে, যা আপনাকে অবজেক্ট অ্যালোকেশন হায়ারার্কি দেখতে, রিটেইনড মেমরির আকার গণনা করতে এবং গার্বেজ কালেকশন রুট থেকে সংক্ষিপ্ততম পথ শনাক্ত করতে সাহায্য করে। হিপ ডাম্প এক্সপ্লোরার ব্যবহার করে, আপনি দ্রুত মেমরি লিক, অতিরিক্ত বিটম্যাপ অ্যালোকেশনের মতো স্ফীত রিটেইনড অবজেক্ট চিহ্নিত করতে এবং হিপ অবজেক্ট অ্যালোকেশন বিশ্লেষণ করতে পারবেন—সবকিছু এক জায়গায়।

উপসংহার
R8 ব্যবহার করে বাইটকোড অপ্টিমাইজ করা, ইমেজ লোডিংয়ের সেরা পদ্ধতিগুলো অনুসরণ করা এবং মেমরি লিকের সমাধান করা হলো এমন কিছু গুরুত্বপূর্ণ পদক্ষেপ যা চাপের মধ্যে কার্যকরভাবে রিসোর্স ব্যবস্থাপনার পাশাপাশি একটি উচ্চ-মানের ব্যবহারকারীর অভিজ্ঞতা নিশ্চিত করে। এই সক্রিয় পদক্ষেপগুলো গ্রহণ করলে অ্যাপের স্থিতিশীলতা ও পারফরম্যান্স বজায় থাকে, অপ্রত্যাশিতভাবে অ্যাপ বন্ধ হয়ে যাওয়া প্রতিরোধ করা যায় এবং ব্যবহারকারীর কনটেক্সট সুরক্ষিত থাকে। পারফরম্যান্স বিষয়ে আপনার দক্ষতা আরও বাড়াতে, আমাদের সংশোধিত মেমরি নির্দেশিকাটি দেখুন।
কীভাবে করবেনঅ্যান্ড্রয়েড ব্যবহারকারীদের জন্য অতিরিক্ত ব্যাটারি খরচ একটি প্রধান উদ্বেগের বিষয়, এটা উপলব্ধি করে গুগল ডেভেলপারদের আরও শক্তি-সাশ্রয়ী অ্যাপ তৈরিতে সাহায্য করার জন্য গুরুত্বপূর্ণ পদক্ষেপ নিচ্ছে।
Alice Yuan • পড়তে ৮ মিনিট
কীভাবে করবেনপারফরম্যান্স লেভেলিং গাইডে ৫টি স্তর রয়েছে। আমরা লেভেল ১ দিয়ে শুরু করব, যা ন্যূনতম প্রচেষ্টায় গ্রহণ করা যায় এমন পারফরম্যান্স টুলিংয়ের সাথে পরিচয় করিয়ে দেয়, এবং আমরা লেভেল ৫ পর্যন্ত যাব, যা সেইসব অ্যাপের জন্য আদর্শ যাদের একটি নিজস্ব পারফরম্যান্স ফ্রেমওয়ার্ক রক্ষণাবেক্ষণ করার মতো সংস্থান রয়েছে।
Alice Yuan • পড়তে ৯ মিনিট
কীভাবে করবেননতুন ফিচার নিয়ে কাজ করার সময় অ্যাপের পারফরম্যান্স প্রায়শই উপেক্ষিত হয়। তবে, ডেভেলপাররা সবসময় বিষয়টিকে সর্বোচ্চ গুরুত্ব না দিলেও, আপনার অ্যাপের পারফরম্যান্স কোথায় পিছিয়ে আছে তা ব্যবহারকারীরা ঠিকই দেখতে পান।
Ben Weiss • পড়তে ৩ মিনিট
অ্যান্ড্রয়েড ডেভেলপমেন্টের সর্বশেষ তথ্য প্রতি সপ্তাহে আপনার ইনবক্সে পান।




