2016-09-27 136 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