致命异常:android.graphics.BitmapFactory.nativeDecodeStream中的main java.lang.OutOfMemoryError(Native Method)

问题描述:

我在运行我的应用程序时不断收到此错误。该应用程序将编译正常,一旦我开始与它交互(ImageSlider)有时它会中断并提出该消息。致命异常:android.graphics.BitmapFactory.nativeDecodeStream中的main java.lang.OutOfMemoryError(Native Method)

logcat的

02-18 12:25:05.426: E/AndroidRuntime(4545): FATAL EXCEPTION: main 
02-18 12:25:05.426: E/AndroidRuntime(4545): java.lang.OutOfMemoryError 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:299) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at com.oneplc.viessmannapp.imageslider.adapter.FullScreenImageAdapter.instantiateItem(FullScreenImageAdapter.java:59) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:832) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.support.v4.view.ViewPager.populate(ViewPager.java:1016) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.support.v4.view.ViewPager.populate(ViewPager.java:914) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.support.v4.view.ViewPager$3.run(ViewPager.java:244) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.support.v4.view.ViewPager.completeScroll(ViewPager.java:1761) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.support.v4.view.ViewPager.onInterceptTouchEvent(ViewPager.java:1894) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1629) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1684) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1684) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1684) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1684) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1917) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1371) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.app.Activity.dispatchTouchEvent(Activity.java:2364) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1865) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.view.View.dispatchPointerEvent(View.java:5721) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:2890) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2466) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.view.ViewRootImpl.processInputEvents(ViewRootImpl.java:845) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2475) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.os.Handler.dispatchMessage(Handler.java:99) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.os.Looper.loop(Looper.java:137) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at android.app.ActivityThread.main(ActivityThread.java:4424) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at java.lang.reflect.Method.invokeNative(Native Method) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at java.lang.reflect.Method.invoke(Method.java:511) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
02-18 12:25:05.426: E/AndroidRuntime(4545):  at dalvik.system.NativeStart.main(Native Method) 

在行类,负责/ FullScreenImageAdapter.java:59

public class FullScreenImageAdapter extends PagerAdapter { 

    private Activity _activity; 
    private ArrayList<String> _imagePaths; 
    private LayoutInflater inflater; 

    // constructor 
    public FullScreenImageAdapter(Activity activity, 
      ArrayList<String> imagePaths) { 
     this._activity = activity; 
     this._imagePaths = imagePaths; 
    } 

    @Override 
    public int getCount() { 
     return this._imagePaths.size(); 
    } 

    @Override 
    public boolean isViewFromObject(View view, Object object) { 
     return view == ((RelativeLayout) object); 
    } 

    @Override 
    public Object instantiateItem(ViewGroup container, int position) { 
     TouchImageView imgDisplay; 
     Button btnClose; 

     inflater = (LayoutInflater) _activity 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     View viewLayout = inflater.inflate(R.layout.layout_fullscreen_image, container, 
       false); 

     imgDisplay = (TouchImageView) viewLayout.findViewById(R.id.imgDisplay); 
     btnClose = (Button) viewLayout.findViewById(R.id.btnClose); 

     BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inPreferredConfig = Bitmap.Config.ARGB_8888; 
     Bitmap bitmap = BitmapFactory.decodeFile(_imagePaths.get(position), options); 
     imgDisplay.setImageBitmap(bitmap); 

     // close button click event 
     btnClose.setOnClickListener(new View.OnClickListener() {    
      @Override 
      public void onClick(View v) { 
       _activity.finish(); 
      } 
     }); 

     ((ViewPager) container).addView(viewLayout); 

     return viewLayout; 
    } 

    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 
     ((ViewPager) container).removeView((RelativeLayout) object); 

    } 
} 

评论

我看到一些其他的线程,但他们哪里都不有益的,或者至少不可以在我的情况下实施。

任何想法如何克服这个问题?

+1

你可以使用通用imageLoader类..... – Piyush

+0

那么这是在全屏幕活动实施?我现在正在实施相同的事情,并为我工作得很好。 – Piyush

+0

它很奇怪,因为我自己运行此功能,它工作正常,但是当我将它合并到我的应用程序,我得到内存错误.. – AndroidKrayze

你应该看看这篇关于android dev网站http://developer.android.com/training/displaying-bitmaps/index.html的文章。你应该异步加载位图,因为你的解码文件,其昂贵的操作,你也应该先加载位图的尺寸和比它扩展到的imageview的

你应该使用这个真实大小......

 @Override 
    public Object instantiateItem(ViewGroup container, int position) { 
     final TouchImageView imgDisplay; 

     inflater = (LayoutInflater) _activity 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     View viewLayout = inflater.inflate(
       R.layout.layout_fullscreen_image, container, false); 

     imgDisplay = (TouchImageView) viewLayout 
       .findViewById(R.id.imgDisplay); 
     final ProgressBar spinner = (ProgressBar) viewLayout 
       .findViewById(R.id.loading); 
     // btnShare = (Button) viewLayout.findViewById(R.id.btnShare); 

     imageLoader.displayImage(_imagePaths.get(position).get("url"), 
       imgDisplay, options, new ImageLoadingListener() { 
        @Override 
        public void onLoadingStarted() { 
         spinner.setVisibility(View.VISIBLE); 
        } 

        @Override 
        public void onLoadingFailed(FailReason failReason) { 
         String message = null; 
         switch (failReason) { 
         case IO_ERROR: 
          message = "Input/Output error"; 
          break; 
         case OUT_OF_MEMORY: 
          message = "Out Of Memory error"; 
          break; 
         case UNKNOWN: 
          message = "Unknown error"; 
          break; 
         } 
         Toast.makeText(FullScreenViewActivity.this, 
           message, Toast.LENGTH_SHORT).show(); 

         spinner.setVisibility(View.GONE); 
         imgDisplay 
           .setImageResource(android.R.drawable.ic_delete); 
        } 

        @Override 
        public void onLoadingComplete(Bitmap loadedImage) { 
         spinner.setVisibility(View.GONE); 
         Animation anim = AnimationUtils 
           .loadAnimation(FullScreenViewActivity.this, 
             R.anim.fade_in); 
         imgDisplay.setAnimation(anim); 
         anim.start(); 

        } 

        @Override 
        public void onLoadingCancelled() { 
         // Do nothing 
        } 
       }); 

     ((ViewPager) container).addView(viewLayout, 0); 

     return viewLayout; 
    } 

    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 
     ((ViewPager) container).removeView((FrameLayout) object); 

    } 
} 

添加在onCreate()方法这个代码..

 private DisplayImageOptions options; 

     options = new DisplayImageOptions.Builder() 
      .showImageForEmptyUri(R.drawable.ic_launcher).cacheOnDisc() 
      .imageScaleType(ImageScaleType.IN_SAMPLE_INT).build(); 

添加通用图像装载机-1.6.1-与-src.jar jar文件到您的文件夹。

UPDATE

private DisplayImageOptions options; 
public FullScreenImageAdapter(Activity activity, 
     ArrayList<String> imagePaths) { 
    this._activity = activity; 
    this._imagePaths = imagePaths; 
    options = new DisplayImageOptions.Builder() 
      .showImageForEmptyUri(R.drawable.ic_launcher).cacheOnDisc() 
      .imageScaleType(ImageScaleType.IN_SAMPLE_INT).build(); 
} 
+0

我会尝试它现在Piyush! – AndroidKrayze

+0

Piyush,我的类扩展适配器,不是一个活动,所以这意味着我没有一个onCreate方法。 – AndroidKrayze

+0

您也可以将它添加到您的Adapter类构造函数中。 – Piyush

如果有人试图从sqlite的图像和获取内存不足错误尝试以下操作:

cursor = adapter.getAllrecords(); //get your table records in cursor 

//moving to the current position in cursor 
cursor.moveToPosition(position); 

byte [] image = cursor.getBlob(cursor.getColumnIndex("image")); 

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inJustDecodeBounds = true; 
bitmapImage = BitmapFactory.decodeByteArray(image, 0, image.length, options); 
imageView.setImageBitmap(decodeSampledBitmapFromResource(80, 80));//pass height and    
                 //width as per your requirement 



public 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; 
    } 
     public Bitmap decodeSampledBitmapFromResource(int reqWidth, int reqHeight) { 

      // First decode with inJustDecodeBounds=true 
       to check dimensions 
      final BitmapFactory.Options options = new BitmapFactory.Options(); 
      options.inJustDecodeBounds = true; 
      BitmapFactory.decodeByteArray(image, 0, image.length, options); 

      // Calculate inSampleSize 
      options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

      // Decode bitmap with inSampleSize set 
      options.inJustDecodeBounds = false; 
      return BitmapFactory.decodeByteArray(image, 0, image.length, options); 
     } 

这段代码根据开发商guideliness工作了me..however我们应该使用AsyncTask处理与图像相关的任务...我们不应该在UI线程上运行它。

如果谷歌文档没有帮助(他们有一些巧妙的技巧),作为最后的手段,你可以尝试添加 android:largeHeap="true"AndroidManifest.xml<application>标签。但真的,最后的手段。