অ্যান্ড্রয়েড: বিটম্যাপ পুনরায় ব্যবহার () কীভাবে কাজ করে?


90

ধরা যাক আমি বিটম্যাপ অবজেক্টের মতো একটি চিত্র লোড করেছি

Bitmap myBitmap = BitmapFactory.decodeFile(myFile);

এখন, আমি যদি অন্য একটি বিটম্যাপ পছন্দ করি তবে কী হবে

myBitmap = BitmapFactory.decodeFile(myFile2);

প্রথম মাইবিটম্যাপের কী হবে? এটি কি আবর্জনা সংগ্রহের জন্য পেয়েছে বা অন্য বিটম্যাপ লোড করার আগে আমাকে ম্যানুয়ালি আবর্জনা সংগ্রহ করতে হবে, যেমন। myBitmap.recycle()?

এছাড়াও, পথে পুনর্ব্যবহারের সময় বড় চিত্রগুলি লোড করার এবং একের পর এক সেগুলি প্রদর্শন করার আরও ভাল উপায় কি?

উত্তর:


79

প্রথম বিটম্যাপটি আবশ্যক জঞ্জাল নয় যখন আপনি দ্বিতীয়টি ডিকোড করেন। আবর্জনা সংগ্রহকারী এটি যখনই সিদ্ধান্ত নেবে পরে করবে। আপনি যদি এএসএপকে মেমরি ফ্রি করতে চান recycle()তবে দ্বিতীয় বিটম্যাপটি ডিকোড করার ঠিক আগে আপনার কল করা উচিত ।

আপনি যদি সত্যিই বড় চিত্রটি লোড করতে চান তবে আপনার এটি পুনরায় নমুনা করা উচিত। এখানে একটি উদাহরণ রয়েছে: বিটম্যাপ অবজেক্টে কোনও চিত্র লোড করার সময় মেমরির সমস্যা থেকে অদ্ভুত


24

আমি মনে করি সমস্যাটি হ'ল: অ্যান্ড্রয়েডের প্রাক-হানিকম্ব সংস্করণগুলিতে, আসল কাঁচা বিটম্যাপ ডেটা ভিএম মেমরিতে সংরক্ষণ করা হয় না তবে এর পরিবর্তে নেটিভ মেমোরিতে সংরক্ষণ করা হয়। এই নেটিভ মেমরির হয় যখন সংশ্লিষ্ট জাভা মুক্ত Bitmapবস্তুর GC'd করা হয়।

তবে , যখন আপনি নেটিভ মেমোরি থেকে সরে আসেন, ডালভিক জিসি ট্রিগার হয় না, সুতরাং আপনার অ্যাপটি জাভা স্মৃতি খুব কম ব্যবহার করে, তাই ডালভিক জিসি কখনই না চাওয়া, তবু এটি বিটম্যাপের জন্য প্রচুর দেশীয় মেমরি ব্যবহার করে যা অবশেষে একটি OOM ত্রুটির কারণ হয়ে থাকে।

অন্তত আমার অনুমান। ধন্যবাদ হানিকম্ব এবং তারপরে, সমস্ত বিটম্যাপ ডেটা ভিএম-তে সংরক্ষণ করা হয়েছে যাতে আপনার কোনও ব্যবহার recycle()করার দরকার নেই। কিন্তু 2.3 লক্ষাধিক ব্যবহারকারী (ফ্র্যাগমেন্টেশন জন্য শেকস মুষ্টি ), আপনি ব্যবহার করা উচিত recycle()(ক বৃহদায়তন ঝগড়া) যেখানে সম্ভব। অথবা বিকল্পভাবে আপনি এর পরিবর্তে জিসিকে আবেদন করতে সক্ষম হতে পারেন।


21

পরের চিত্রটি লোড করার আগে আপনাকে আমার বিটম্যাপ.সাইকেল () কল করতে হবে।

আপনার মাইফাইলের উত্সের উপর নির্ভর করে (উদাহরণস্বরূপ, এটি যদি আপনার মূল আকারের উপর কোনও নিয়ন্ত্রণ না করে), কেবল কিছু স্বেচ্ছাসেবী সংখ্যার পুনরায় মডেল করার পরিবর্তে কোনও চিত্র লোড করার সময়, আপনার চিত্রটি প্রদর্শন আকারে স্কেল করা উচিত।

if (myBitmap != null) {
    myBitmap.recycle();
    myBitmap = null;
}
Bitmap original = BitmapFactory.decodeFile(myFile);
myBitmap = Bitmap.createScaledBitmap(original, displayWidth, displayHeight, true);
if (original != myBitmap)
    original.recycle();
original = null;

আমি আমার ক্রিয়াকলাপের শুরুতে যে স্ট্যাটিকটি আরম্ভ করেছি সেটিতে আমি ডিসপ্লেউইথ এবং ডিসপ্লে হাইটকে ক্যাশে রাখি।

Display display = getWindowManager().getDefaultDisplay();
displayWidth = display.getWidth();
displayHeight = display.getHeight();

4
আপনাকে রিসাইকেল () কল করার দরকার নেই, আপনি এখনই স্মৃতি মুক্ত করতে চাইলে এটি কেবল একটি ভাল ধারণা।
করু

13
গৃহীত উত্তরটি বলে "যদি আপনি এএসএপকে মেমরি ফ্রি করতে চান তবে আপনার রিসাইকেল () কল করা উচিত"। আপনার উত্তরটি বলছে "আপনাকে আমার বিটম্যাপ.আরসিচাল ()" কল করতে হবে। "উচিত" এবং "প্রয়োজন" এর মধ্যে পার্থক্য রয়েছে এবং এই ক্ষেত্রেটি পরবর্তী ক্ষেত্রে ভুল।
করু

4
প্রসঙ্গটি গুরুত্বপূর্ণ। প্রশ্নটি ছিল "এছাড়াও বড় চিত্রগুলি লোড করার এবং উপায়গুলিতে একের পর এক পুনরায় চালনার পরে তাদের প্রদর্শন করার আরও ভাল উপায়"।
djodod

4
অ্যান্ড্রয়েড ৪.১-এর হিসাবে উপরের উদাহরণটি ভেঙে যেতে পারে কারণ কিছুটা ক্ষেত্রে ক্রিয়েসেল্ডবিটম্যাপটি আসল উদাহরণের মতো একই পরিস্থিতিতে ফিরে আসতে পারে। তার মানে আপনাকে আসলটি পুনরায় সাইকেল চালানোর আগে তার == MyBitmap টি পরীক্ষা করতে হবে।
জেরেমিফা

4
@ জেরেমিফা এটি কেবলমাত্র মূল চিত্রটি ফিরিয়ে দেয় যদি আপনি এমন কোনও প্রস্থ এবং উচ্চতা নির্দিষ্ট করে যা মূলটির সাথে সমান হয়। সেক্ষেত্রে স্কেলিংটি মোট হয়, সুতরাং এটি এড়িয়ে যাওয়া এবং পরিবর্তে মূল চিত্রটি ফিরিয়ে কিছু প্রক্রিয়া সংরক্ষণ করতে পারে। যদিও "ব্রেক" করা উচিত নয় ...
জাবারি

11

একবার বিটম্যাপটি স্মৃতিতে লোড হয়ে গেছে, আসলে এটি দুটি অংশের ডেটা দ্বারা তৈরি হয়েছিল। প্রথম অংশে বিটম্যাপ সম্পর্কে কিছু তথ্য অন্তর্ভুক্ত রয়েছে, অন্য অংশে বিটম্যাপের পিক্সেল সম্পর্কে তথ্য অন্তর্ভুক্ত রয়েছে (এটি বাইট অ্যারে দ্বারা প্রস্তুত করা হয়েছে)। জাভা ব্যবহৃত স্মৃতিতে প্রথম অংশের উপস্থিতি রয়েছে, দ্বিতীয় অংশটি সি ++ ব্যবহৃত মেমরির মধ্যে রয়েছে। এটি একে অপরের স্মৃতি সরাসরি ব্যবহার করতে পারে। বিটম্যাপ.রেইসিএল () সি ++ এর স্মৃতি মুক্ত করতে ব্যবহৃত হয়। আপনি যদি কেবল এটি করেন, জিসি জাভা অংশ সংগ্রহ করবে এবং সি এর মেমরি সর্বদা ব্যবহৃত হবে।


মেমরিটি কেন তাত্ক্ষণিক জিসির জন্য পাওয়া যায় না তা বর্ণনা করার একটি আকর্ষণীয় তবে খুব ভাল পদ্ধতির জন্য +1 - দুর্দান্ত।
রিচার্ড লে ম্যাসুরিয়ার

8

টিমম্মম ঠিক ছিল।

অনুসারে: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

এছাড়াও, অ্যান্ড্রয়েড 3.0.০ (এপিআই লেভেল ১১) এর পূর্বে, বিটম্যাপের ব্যাকিং ডেটা দেশীয় মেমরিতে সংরক্ষণ করা হয়েছিল যা অনুমানযোগ্যভাবে প্রকাশ করা হয় না, সম্ভবত কোনও অ্যাপ্লিকেশনটি সংক্ষিপ্তভাবে এর স্মৃতি সীমা এবং ক্র্যাশ ছাড়িয়ে যায়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.