2013-08-22 7 views
15

मैं गैलेक्सी एस 4 के लिए एक एप्लीकेशन विकसित कर रहा हूं। एप्लिकेशन की आवश्यकताओं में से एक में स्प्लैशस्क्रीन है जिसमें 1920x1080 पिक्सेल की छवि शामिल है। इसकी एक उच्च गुणवत्ता .jpeg छवि और छवि का आकार लगभग 2 मेगाबाइट है।उच्च रिज़ॉल्यूशन छवि - OutOfMemoryError

समस्या यह है कि मुझे आउटऑफमेमरी एरर जैसे ही मैं एप्लिकेशन शुरू करता हूं। मैं काफी डर गया हूं कि यह आकार में केवल 2 मेगाबाइट की छवि के साथ पहले से ही होता है? मैं इस समस्या को कैसे ठीक कर सकता हूं और छवि प्रदर्शित कर सकता हूं?

आयाम या छवि का आकार बदलना एक विकल्प नहीं है।

SplashScreen.java

public class Splashscreen extends Activity { 

private static final int SPLASH_DURATION = 2000; 
private boolean isBackPressed = false; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 

    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    getWindow().setFlags(LayoutParams.FLAG_FULLSCREEN, LayoutParams.FLAG_FULLSCREEN); 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.splashscreen); 

    Handler h = new Handler(); 

    h.postDelayed(new Runnable() { 

     @Override 
     public void run() { 

      // check if the backbutton has been pressed within the splash_duration 
      if(!isBackPressed) { 

       Intent i = new Intent(Splashscreen.this, MainActivity.class); 
       i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
       Splashscreen.this.startActivity(i); 
       overridePendingTransition(R.anim.short_fade_in, R.anim.short_fade_out); 
      }  

      finish(); 
     } 
    }, SPLASH_DURATION); 
} 

@Override 
public void onBackPressed() { 

    isBackPressed = true; 
    super.onBackPressed(); 
} 
} 

और splashscreen.xml

<ImageView 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     android:id="@+id/ivSplashScreenImage" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:scaleType="fitXY" 
     android:src="@drawable/high_res_splashscreen_image"/> 

अतिरिक्त जानकारी:

कभी कभी, (जब डिवाइस स्मृति का एक बहुत उपलब्ध है) ऐप इसे स्प्लैश स्क्रीन से पहले बनाने में सक्षम है, लेकिन फिर, ऐप की मेमोरी खपत सिर्फ पागल है(लगभग 100 मेगाबाइट)। भले ही मैं स्प्लैशस्क्रीन गतिविधि बंद करता हूं और इसे समाप्त करता हूं (ऐसा लगता है कि छवि दृश्य/स्मृति में रखी गई छवि का संदर्भ है।

मैं बड़ी मेमोरी खपत को कैसे कम कर सकता हूं?

जब मैं स्प्लैश स्क्रीन प्रदर्शित नहीं करते, मेरा ऐप्स केवल स्मृति के 35MB आसपास खपत करता है। स्प्लैशस्क्रीन छवि के साथ, इसके लगभग 100 एमबी।

+0

[इसे देखें] (http://stackoverflow.com/questions/477572/strange-out-of-memory-issue-while-loading-an-image-to-a-bitmap-object) –

+0

क्या आपके पास है आपके res फ़ोल्डर में बहुत सारी छवि फ़ाइलें ?? –

+0

हां, मेरे पास लगभग 40 छवि फ़ाइलें हैं। लेकिन वे आकार में 10 और 50 केबी के बीच होने वाले बहुत बड़े नहीं हैं (केवल उनमें से अधिकांश प्रतीक)। –

उत्तर

13

तीन संकेत है जो आप की मदद करनी चाहिए:

  1. उपयोग इस अपनी छवियों को लोड करने के लिए, Loading Large Bitmaps Android documentation से:

    public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
         int reqWidth, int reqHeight) { 
    
        // First decode with inJustDecodeBounds=true to check dimensions 
        final BitmapFactory.Options options = new BitmapFactory.Options(); 
        options.inJustDecodeBounds = true; 
        BitmapFactory.decodeResource(res, resId, options); 
    
        // Calculate inSampleSize 
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 
    
        // Decode bitmap with inSampleSize set 
        options.inJustDecodeBounds = false; 
        return BitmapFactory.decodeResource(res, resId, options); 
    } 
    
    public static int calculateInSampleSize(
          BitmapFactory.Options options, int reqWidth, int reqHeight) { 
        // Raw height and width of image 
        final int height = options.outHeight; 
        final int width = options.outWidth; 
        int inSampleSize = 1; 
    
        if (height > reqHeight || width > reqWidth) { 
    
         // Calculate ratios of height and width to requested height and width 
         final int heightRatio = Math.round((float) height/(float) reqHeight); 
         final int widthRatio = Math.round((float) width/(float) reqWidth); 
    
         // Choose the smallest ratio as inSampleSize value, this will guarantee 
         // a final image with both dimensions larger than or equal to the 
         // requested height and width. 
         inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; 
        } 
    
        return inSampleSize; 
    } 
    
  2. सुनिश्चित करें कि आप स्मृति में अपने Bitmap उसमें केवल एक ही किया हुआ है । इसे प्रदर्शित करने के बाद, recycle() पर कॉल करें और अपना संदर्भ null पर सेट करें। आवंटित किए गए देखने के लिए आप Memory Allocation Tracker का उपयोग कर सकते हैं। टिप्पणियों में सुझाए गए अनुसार, आप एचपीआरओएफ फाइल भी पढ़ सकते हैं।

  3. डिफ़ॉल्ट रूप से ARGB_8888 पिक्सेल प्रारूप का उपयोग किया जाता है, जिसका अर्थ है 4 बाइट प्रति पिक्सेल। बहुत अच्छा लेख: Bitmap quality, banding and dithering। आपकी छवि जेपीईजी है, इसलिए इसमें पारदर्शिता नहीं है, इसलिए आप अल्फा चैनल के लिए प्रत्येक पिक्सेल पर 1 बाइट बर्बाद कर रहे हैं। यह बहुत संभव नहीं है, लेकिन शायद स्वीकार्य गुणवत्ता के साथ आप और भी किफायती प्रारूप का उपयोग कर सकते हैं। Take उन पर एक नज़र डालें। उदाहरण के लिए शायद RGB_565। इसमें पिक्सेल के लिए 2 बाइट लगते हैं, इसलिए आपकी छवि 50% हल्की होगी। आप RGB_565 की गुणवत्ता में सुधार करने के लिए दांत सक्षम कर सकते हैं।

+0

धन्यवाद, मैं कोशिश करूँगा। कृपया मेरे अपडेट किए गए उत्तर और "अतिरिक्त जानकारी" –

+1

पर एक नज़र डालें। मैंने छवि संसाधन को .xml फ़ाइल में "@null" पर सेट किया है और अब इस तरह की छवि लोड करें: "((ImageView) findViewById (R.id.ivSplashScreenImage))। setImageBitmap (decodeSampledBitmapFromResource (getResources(), R.drawable.highres, 1920, 1080)); " अब मैं स्प्लैशस्क्रीन से बाहर निकलने में सक्षम हूं लेकिन मेरी ऐप मेमोरी खपत अभी भी करीब 9 0 एमबी है। (स्प्लैश स्क्रीन के बिना, इसकी 35-40 एमबी) –

+1

सिद्धांत रूप में, 1920x1080 आकार का बिटमैप केवल 8 एमबी होना चाहिए। क्या आप यह सुनिश्चित करने के लिए एक एचपीआरओएफ डंप पर एक नज़र डाल सकते हैं कि आप इन बिटमैप्स में से केवल एक आवंटित कर रहे हैं? अब जब आप छवि को मैन्युअल रूप से लोड कर रहे हैं, तो आपको स्प्लैश स्क्रीन बंद होने के बाद इसे रीसायकल करना सुनिश्चित करना चाहिए और इसके संदर्भ को रद्द करना चाहिए। [एंड्रॉइड अनुप्रयोगों के लिए मेमोरी विश्लेषण] (http://android-developers.blogspot.com/2011/03/memory-analysis-for-android.html) –

5

मुझे एक ही समस्या थी और समाधान सरल है। drawable-nodpi निर्देशिका में अपना उच्च रिज़ॉल्यूशन 1920x1080 पीएक्स छवि डालें। सिस्टम वर्तमान क्वालिफायर के साथ टैग किए गए संसाधनों को स्केल नहीं करता है, चाहे वर्तमान स्क्रीन की घनत्व के बावजूद, आउटऑफमेमरी एरर की ओर जाता है, इसलिए समस्या गायब होनी चाहिए।

की जांच करें Android दस्तावेज़: http://developer.android.com/intl/es/guide/practices/screens_support.html

आशा है कि यह मदद करता है।

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