2012-08-05 12 views
56

मेरे एप्लिकेशन स्रोत में निम्न पंक्ति में एक OOM त्रुटि मार जाता है:एंड्रॉयड: BitmapFactory.decodeStream() 2 एमबी मुफ्त ढेर के साथ एक 400KB फ़ाइल के साथ स्मृति से बाहर

image = BitmapFactory.decodeStream(assetManager.open(imgFilename)); 

से ठीक पहले आवंटन कि का कारण बनता है एप्लिकेशन को किसी OOM त्रुटि के साथ मारे जाने के लिए:

Heap Size: 5.254 MB 
Allocated: 2.647 MB 
Free: 2.607 MB 
%Used: 50.38% 
#Objects 49,028 
:

(...) 
08-05 21:22:12.443: I/dalvikvm-heap(2319): Clamp target GC heap from 25.056MB to 24.000MB 
08-05 21:22:12.443: D/dalvikvm(2319): GC_FOR_MALLOC freed <1K, 50% free 2709K/5379K, external 18296K/19336K, paused 58ms 
08-05 21:22:14.513: D/dalvikvm(2319): GC_EXTERNAL_ALLOC freed <1K, 50% free 2709K/5379K, external 18296K/19336K, paused 101ms 
08-05 21:22:14.903: I/dalvikvm-heap(2319): Clamp target GC heap from 25.073MB to 24.000MB 
08-05 21:22:14.903: D/dalvikvm(2319): GC_FOR_MALLOC freed 0K, 50% free 2709K/5379K, external 18312K/19336K, paused 53ms 
08-05 21:22:22.843: D/ddm-heap(2319): Heap GC request 
08-05 21:22:22.963: I/dalvikvm-heap(2319): Clamp target GC heap from 25.073MB to 24.000MB 
08-05 21:22:22.963: D/dalvikvm(2319): threadid=1: still suspended after undo (sc=1 dc=1) 
08-05 21:22:22.963: D/dalvikvm(2319): GC_EXPLICIT freed 1K, 50% free 2710K/5379K, external 18312K/19336K, paused 116ms 

डी डी एम एस ढेर की स्थिति के बारे में एक समान चित्र की रिपोर्ट 210

एक OOM गलती से यह लाइन परिणामों पर एकल स्टेपिंग:

08-05 21:26:04.783: D/dalvikvm(2319): GC_EXTERNAL_ALLOC freed <1K, 50% free 2710K/5379K, external 18312K/19336K, paused 57ms 
08-05 21:26:05.023: E/dalvikvm-heap(2319): 2097152-byte external allocation too large for this process. 
08-05 21:26:05.163: I/dalvikvm-heap(2319): Clamp target GC heap from 25.073MB to 24.000MB 
08-05 21:26:05.163: E/GraphicsJNI(2319): VM won't let us allocate 2097152 bytes 
08-05 21:26:05.163: D/dalvikvm(2319): GC_FOR_MALLOC freed 0K, 50% free 2710K/5379K, external 18312K/19336K, paused 30ms 
08-05 21:26:05.283: D/skia(2319): --- decoder->decode returned false 
  1. "imgFileName" द्वारा संदर्भित फ़ाइल का आकार विंडोज पर < 400K होने की सूचना दी है। तो BitmapFactory.decodeStream 2 एमबी आवंटित करने का प्रयास क्यों करता है?
  2. पर्याप्त खाली जगह होने पर ओओएम त्रुटि क्यों होती है?

यह ऐप एंड्रॉइड 2.2 और ऊपर लक्षित कर रहा है।

अग्रिम धन्यवाद!

उत्तर

71

एंड्रॉइड लाइब्रेरी छवियों को लोड करने के लिए इतना स्मार्ट नहीं है, इसलिए आपको इसके लिए वर्कअराउंड बनाना होगा।

मेरे परीक्षणों में, Drawable.createFromStreamBitmapFactory.decodeStream से अधिक मेमोरी का उपयोग करता है।

आप स्मृति (RGB_565) कम करने के लिए रंग योजना बदल सकते हैं, लेकिन छवि गुणवत्ता भी खो देंगे:

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inPreferredConfig = Config.RGB_565; 
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options); 

संदर्भ: http://developer.android.com/reference/android/graphics/Bitmap.Config.html

तुम भी एक आकार बदली गई चित्र लोड कर सकते हैं, कम हो जाएगा जो बहुत मेमोरी उपयोग, लेकिन आपको अपनी छवियों को बहुत अधिक गुणवत्ता खोने के लिए नहीं जानना है।

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inSampleSize = 2; 
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options); 

संदर्भ: http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html

गतिशील inSampleSize को परिभाषित करने के लिए, आप छवि का आकार पता करने के लिए अपने निर्णय लेने के लिए चाहते हो सकता है: स्क्रीन आकार के अनुसार

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inJustDecodeBounds = true; 
bitmap = BitmapFactory.decodeStream(stream, null, options); 
int imageHeight = options.outHeight; 
int imageWidth = options.outWidth; 

options.inJustDecodeBounds = false; 
// recreate the stream 
// make some calculation to define inSampleSize 
options.inSampleSize = ?; 
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options); 

आप inSampleSize अनुकूलित कर सकते हैं डिवाइस का स्क्रीन आकार पाने के लिए, आप कर सकते हैं:

DisplayMetrics metrics = new DisplayMetrics(); 
((Activity) activity).getWindowManager().getDefaultDisplay().getMetrics(metrics); 
int screenWidth = metrics.widthPixels; 
int screenHeight =metrics.heightPixels; 

अन्य ट्यूटोरियल: - http://developer.android.com/training/displaying-bitmaps/load-bitmap.html - http://developer.android.com/training/displaying-bitmaps/index.html

+1

गतिशील रूप से नमूना आकार में गणना करने के लिए छवि आकार की गणना कैसे कर सकता है? – NinjaCoder

+1

मैंने आपके प्रश्न के उत्तर सहित प्रश्न संपादित किया है! –

+1

स्क्रीन का आकार छवि का आकार नहीं है। मेरे पास एक ऐसा एप्लिकेशन है जो उपयोगकर्ता को फोटो लेने या चुनने देता है। एक तस्वीर लेना डिवाइस के पूर्ण कैमरा संकल्प या सेटिंग्स के आधार पर कम इस्तेमाल कर सकता है। एक फोटो चुनना * किसी * आकार का हो सकता है और इसे पिकासा स्टोरेज इत्यादि के कारण स्थानीय नहीं होना चाहिए। इसलिए मेरे ऐप को यूआरआई वापस मिल जाता है। यह जानने का कोई तरीका नहीं है कि उस यूआरआई के नीचे क्या है और न ही आकार पता है। तो मैं नमूना आकार को क्या सेट करूं? मुझे विश्वास नहीं है कि ऐसा करने का कोई अच्छा तरीका नहीं है। – Paul

8

डिस्क पर फ़ाइल का आकार स्मृति में फ़ाइल के आकार के साथ मेल नहीं खाता है। संभावना है कि फ़ाइल संपीड़ित हो, जो डीकोड किए जाने पर नहीं होंगे। आपको इसकी गणना में इसके लिए खाते की आवश्यकता है।

छवि के इन-मेमोरी आकार को प्राप्त करने के लिए छवि की रंग गहराई से छवि (चौड़ाई x ऊंचाई) के आकार को गुणा करें।

41

कृपया अधिक कुशलता से बड़े बिटमैप लोड हो रहा है पर एक गाइड के लिए यह देखें:

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

एक 400 KB छवि फ़ाइल आसानी से रैम 5-10 एमबी तक का समय लग सकता है।

+25

मेरे पास अभी भी इस Google की सिफारिश के साथ आउटऑफमेमरी त्रुटि है ... परेशान। –

3

असल में आप अपने Bitmap को स्केल करने का प्रयास करके अपनी समस्या का समाधान कर सकते हैं और आपको स्मृति खपत कम दिखाई देगी। ऐसा करने के लिए आप here दिखाए गए तरीके की प्रतिलिपि बना सकते हैं।

इसके अलावा, एंड्रॉइड डेवलपर्स में एक समर्पित पृष्ठ है जो आपको बड़ी बिटमैप्स को लोड करने के तरीके को बेहतर ढंग से समझने में मदद कर सकता है। आधिकारिक documentation पर एक नज़र डालें।

1

ऊपर जवाब स्पष्ट रूप से सही हैं, लेकिन एक बेहतर अभ्यास स्पष्ट रूप से सेट को imageView के भी है बिटमैप/src property शून्य, जब उनका उपयोग नहीं किया जाता है, अधिकतर जब आपकी गतिविधि नष्ट हो जाती है। कोई अन्य भारी शुल्क संसाधन (बड़ा टेक्स्ट, ऑडियो, वीडियो) इत्यादि भी हटाया जा सकता है। यह सुनिश्चित करता है कि संसाधन तुरंत मुक्त हो जाएं, और जीसी एकत्र करने की प्रतीक्षा न करें।

+0

समुदाय, क्या आप इस दृष्टिकोण पर कुछ प्रतिक्रिया दे सकते हैं! –

-1

मैं 2 के द्वारा नमूना आकार बदलता हूं। मेरी समस्या हल हो गई है। लेकिन सुनिश्चित करें कि छवि की गुणवत्ता नष्ट नहीं होती है।

+1

बस आप जो करते हैं उसे जानने के बिना नमूना आकार में बदलना, न ही इसे समझाएं, जवाब नहीं होना चाहिए। – JacksOnF1re

संबंधित मुद्दे