2016-09-27 139 views
2

我有一個線性佈局兩個,我正在以編程方式添加圖像視圖。我正在使用imageView.setImageBitmap(bitmap);設置圖像。我得到一個內存不足錯誤。通過https://developer.android.com/training/displaying-bitmaps/process-bitmap.html閱讀後,我決定在一個異步任務中設置圖像位圖,但我仍然得到相同的錯誤。這種錯誤並不一致,有時我得到它。我的Async Task類是這個代碼。致命異常:Android中doInBackground()方法中的異步任務java.lang.OutOfMemoryError?

class SetImageInAsync extends AsyncTask<String, String, ImageWrapper>{ 
    ImageView imageView; 
    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 
     imageView = new ImageView(DisplayContent.this); 
     LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); 
     layoutParams.setMargins(16,16,16,16); 
     imageView.setLayoutParams(layoutParams); 
     imageView.setScaleType(ImageView.ScaleType.FIT_XY); 
     web_linearLayout.addView(imageView); 

    } 

    @Override 
    protected ImageWrapper doInBackground(String... params) 
    { 
     Uri image_uri = Uri.fromFile(new File("/sdcard/rreadyreckoner_images/" + params[0])); 
     Bitmap mBitmap = null; 
     try { 
      mBitmap = MediaStore.Images.Media.getBitmap(DisplayContent.this.getContentResolver(), image_uri); 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     ImageWrapper w = new ImageWrapper(); 
     w.bitmap = mBitmap; 
     w.filename = params[0]; 
     return w; 
    } 

    @Override 
    protected void onPostExecute(final ImageWrapper imgWR) { 

     Bundle extras = getIntent().getExtras(); 
     final String subcategory = extras.getString("subcategory"); 
     imageView.setAdjustViewBounds(true); 
     imageView.setScaleType(TouchImageView.ScaleType.FIT_CENTER); 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 
      imageView.setCropToPadding(false); 
     } 
     imageView.setImageBitmap(imgWR.bitmap); 
     imageView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) 
      { 
       Intent intent = new Intent(DisplayContent.this,DisplayImage.class); 
       intent.putExtra("filename",imgWR.filename); 
       intent.putExtra("subcategory",subcategory); 
       startActivity(intent); 


      } 
     }); 


    } 
} 

這是錯誤日誌中我得到: -

09-27 15:10:07.587 10366-10898/com.inevitable.org.tab_sample E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1 
Process: com.inevitable.org.tab_sample, PID: 10366 
java.lang.RuntimeException: An error occured while executing doInBackground() 
at android.os.AsyncTask$3.done(AsyncTask.java:300) 
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355) 
at java.util.concurrent.FutureTask.setException(FutureTask.java:222) 
at java.util.concurrent.FutureTask.run(FutureTask.java:242) 
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
at java.lang.Thread.run(Thread.java:841) 
Caused by: java.lang.OutOfMemoryError 
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 
at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:736) 
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:712) 
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:750) 
at android.provider.MediaStore$Images$Media.getBitmap(MediaStore.java:830) 
at com.inevitable.org.tab_sample.DisplayContent$SetImageInAsync.doInBackground(DisplayContent.java:236) 
at com.inevitable.org.tab_sample.DisplayContent$SetImageInAsync.doInBackground(DisplayContent.java:216) 
at android.os.AsyncTask$2.call(AsyncTask.java:288) 
at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)  
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)  
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)  
at java.lang.Thread.run(Thread.java:841)  

我是新來的編程所以任何幫助或建議是appreciated.Thank你。

+0

問題是在這一行** mBitmap = MediaStore.Images.Media.getBitmap(DisplayContent.this.getContentResolver(),image_uri); **檢查出這個http://stackoverflow.com/questions/11381113/ mediastore圖像,媒體getbitmap和出內存不足的錯誤 –

+0

謝謝@brahmyadigopula我試過這個鏈接http://tutorials-android.blogspot.in/2011/11/outofmemory-exception-when-decoding。現在的圖像顯示,但他們扭曲。 – AndroidNewBee

+0

再次閱讀該博客有** samplesize **屬性需要一個位圖,並將其高度和寬度降低到其原始大小的20%(1/5)。 inSampleSize N(在我們的例子中N = 5)的值越大,位圖的尺寸越小。 –

回答

3

位圖可能是太大,造成OOM。這不是一個線程問題。

你應該閱讀這一點,這是一個很好的起點。這對包括我自己在內的許多Android開發人員都很有幫助。

Loading Large Bitmaps Efficiently

+0

@AndroidNewBee此外,使用Bitmap.Config.ARGB_8888和Bitmap.Config.RGB_565之間的差別是巨大的,而且對內存消耗大的影響。我建議仔細閱讀這些部分,因爲它幫助了我很多。祝你好運:) – Lev

+0

謝謝@Lev。你能告訴我什麼資源ID應該爲圖像提供,因爲我從我的Java代碼動態添加它。 – AndroidNewBee

1

我使用的樣本代碼從這個例子http://tutorials-android.blogspot.in/2011/11/outofmemory-exception-when-decoding.html通過@brahmyadigopula的建議。

// Read bitmap 
    public Bitmap readBitmap(Uri selectedImage) { 
     Bitmap bm = null; 

     // First decode with inJustDecodeBounds=true to check dimensions 
     final BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 



     AssetFileDescriptor fileDescriptor =null; 
     try { 
      fileDescriptor = this.getContentResolver().openAssetFileDescriptor(selectedImage,"r"); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } 
     finally{ 
      try { 
       bm = BitmapFactory.decodeFileDescriptor(fileDescriptor.getFileDescriptor(), null, options); 

       // Calculate inSampleSize 
       options.inSampleSize = calculateInSampleSize(options,200, 200); 

       // Decode bitmap with inSampleSize set 
       options.inJustDecodeBounds = false; 
       bm = BitmapFactory.decodeFileDescriptor(fileDescriptor.getFileDescriptor(), null, options); 


       fileDescriptor.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
     return bm; 
    } 

然後在樣本大小使用下面的代碼在計算https://developer.android.com/training/displaying-bitmaps/load-bitmap.html通過@Lev的建議。

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) { 

     final int halfHeight = height/2; 
     final int halfWidth = width/2; 

     // Calculate the largest inSampleSize value that is a power of 2 and keeps both 
     // height and width larger than the requested height and width. 
     while ((halfHeight/inSampleSize) >= reqHeight 
       && (halfWidth/inSampleSize) >= reqWidth) { 
      inSampleSize *= 2; 
     } 
    } 

    return inSampleSize; 
} 

,並用它如下: -

Uri image_uri = Uri.fromFile(new File("/sdcard/rreadyreckoner_images/" + params[0])); 

      Bitmap mBitmap = readBitmap(image_uri); 

謝謝@Lev和@brahmyadigopula您guidance.Keep了良好的工作。

+0

我投了你的嘗試和成功的結果。 –

+0

感謝兄弟。快樂編碼。 – AndroidNewBee

+0

@AndroidNewBee好人,幹得好。很高興爲您服務。 – Lev