内存错误与图像有关

时间:2011-10-12 08:46:31

标签: android listview image-processing

我在listview中显示图像并且出现内存错误任何人指导我这个问题的解决方案是什么,这是我的代码

logcat的

ERROR/AndroidRuntime(1010): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
ERROR/AndroidRuntime(1010):     at android.graphics.BitmapFactory.nativeDecodeByteArray(Native Method)
ERROR/AndroidRuntime(1010):     at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:405)
ERROR/AndroidRuntime(1010):     at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:418)
ERROR/AndroidRuntime(1010):     at com.Adapters.AdapterTours.getView(AdapterTours.java:73)
ERROR/AndroidRuntime(1010):     at android.widget.AbsListView.obtainView(AbsListView.java:1409)
ERROR/AndroidRuntime(1010):     at android.widget.ListView.makeAndAddView(ListView.java:1745)
ERROR/AndroidRuntime(1010):     at android.widget.ListView.fillUp(ListView.java:700)
ERROR/AndroidRuntime(1010):     at android.widget.ListView.fillGap(ListView.java:646)
ERROR/AndroidRuntime(1010):     at android.widget.AbsListView.trackMotionScroll(AbsListView.java:3399)
ERROR/AndroidRuntime(1010):     at android.widget.AbsListView.onTouchEvent(AbsListView.java:2233)
ERROR/AndroidRuntime(1010):     at android.widget.ListView.onTouchEvent(ListView.java:3446)
ERROR/AndroidRuntime(1010):     at android.view.View.dispatchTouchEvent(View.java:3885)
ERROR/AndroidRuntime(1010):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:903)
ERROR/AndroidRuntime(1010):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
ERROR/AndroidRuntime(1010):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
ERROR/AndroidRuntime(1010):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
ERROR/AndroidRuntime(1010):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
ERROR/AndroidRuntime(1010):     at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1691)
ERROR/AndroidRuntime(1010):     at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1125)
ERROR/AndroidRuntime(1010):     at android.app.Activity.dispatchTouchEvent(Activity.java:2096)
ERROR/AndroidRuntime(1010):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1675)
ERROR/AndroidRuntime(1010):     at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2194)
ERROR/AndroidRuntime(1010):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1878)
ERROR/AndroidRuntime(1010):     at android.os.Handler.dispatchMessage(Handler.java:99)
ERROR/AndroidRuntime(1010):     at android.os.Looper.loop(Looper.java:130)
ERROR/AndroidRuntime(1010):     at android.app.ActivityThread.main(ActivityThread.java:3683)
ERROR/AndroidRuntime(1010):     at java.lang.reflect.Method.invokeNative(Native Method)
ERROR/AndroidRuntime(1010):     at java.lang.reflect.Method.invoke(Method.java:507)
ERROR/AndroidRuntime(1010):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
ERROR/AndroidRuntime(1010):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
ERROR/AndroidRuntime(1010):     at dalvik.system.NativeStart.main(Native Method)

GetView方法

public View getView(final int position, View convertView, ViewGroup parent) {

      ViewHolder holder;

      if (convertView == null) {
        convertView = mInflater.inflate(R.layout.list_tours, null);
        holder = new ViewHolder();
        holder.tourTitle = (TextView) convertView.findViewById(R.id.tourTitle);
        holder.tourIcon = (ImageView) convertView.findViewById(R.id.tourIcon);
        holder.tourDetail = (TextView) convertView.findViewById(R.id.tourDetail);
        convertView.setTag(holder);

      } else {
        holder = (ViewHolder) convertView.getTag();
      }


      DalTours tour = getItem(position);

        String tempTag = String.valueOf(tour.getId());
        holder.tourIcon.setTag(tempTag);

        if(tour.getImageByteArray() != null)
        {
            Bitmap image = BitmapFactory.decodeByteArray(tour.getImageByteArray(), 0, tour.getImageByteArray().length);
            holder.tourIcon.setImageDrawable(getScaledImage(image));
            image = null;

        }else
        {


            holder.tourIcon.setTag(tour);
            Bitmap cachedImage = ImageLoader.loadBitmap(tour,new ImageLoader.ImageCallback() {

                @Override
                public void imageLoaded(Bitmap imageBitmap, DalTours tour) {
                    ImageView image = (ImageView)listview.findViewWithTag(tour);
                     if(image != null)
                      {

                      try
                      {  
                          ByteArrayOutputStream stream = new ByteArrayOutputStream();
                          if(imageBitmap != null)
                          {


                              image.setImageDrawable(getScaledImage(imageBitmap));
                              imageBitmap.compress(CompressFormat.PNG, 0 ,stream);
                              byte[] bitmapdata = stream.toByteArray();
                              tours.get(position).setImageByteArray(bitmapdata);


                         }
                          stream = null;
                      }finally
                      {

                      }
                      }

                }
            });
              holder.tourIcon.setImageDrawable(getScaledImage(cachedImage));

        }

      holder.tourTitle.setText(tours.get(position).getTitle());
      holder.tourDetail.setText(tours.get(position).getDetail());

      return convertView;
    }

图像缩放功能

 public Drawable getScaledImage(Bitmap actualBitmap)
    {
        BitmapDrawable bmd= null;
        if(actualBitmap != null)
        {

            int width = actualBitmap.getWidth();
            int height = actualBitmap.getHeight();

            Activity parent = (Activity)context;
            Display display = parent.getWindowManager().getDefaultDisplay(); 
            int Screenwidth = display.getWidth();
            int Screenheight = display.getHeight();


         float newWidth = (Screenwidth*35)/100;

         float temp = newWidth / width;
         float newHeight =  temp * height;



        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;

        Matrix matrix = new Matrix();

        matrix.postScale(scaleWidth, scaleHeight);
        Bitmap resizedBitmap = Bitmap.createBitmap(actualBitmap, 0, 0, 
                          width, height, matrix, true); 

        bmd = new BitmapDrawable(resizedBitmap);
        }
        return bmd;

    }

Image Loader Class

public  class ImageLoader {
    private static HashMap<String, SoftReference<Bitmap>> imageCache;

    public ImageLoader() {
        //imageCache = new HashMap<String, SoftReference<Bitmap>>();
    }

    public static Bitmap loadBitmap(final DalTours tour, final ImageCallback imageCallback) {
        if(imageCache == null)
            imageCache = new HashMap<String, SoftReference<Bitmap>>();

        if (imageCache.containsKey(tour.getImageurl())) {
            SoftReference<Bitmap> softReference = imageCache.get(tour.getImageurl());
            Bitmap Bitmap = softReference.get();
            if (Bitmap != null) {
                return Bitmap;
            }
        }
        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message message) {
                imageCallback.imageLoaded((Bitmap) message.obj, tour);
            }
        };
        new Thread() {
            @Override
            public void run() {
                Bitmap Bitmap = loadImageFromUrl(tour.getImageurl());
                imageCache.put(tour.getImageurl(), new SoftReference<Bitmap>(Bitmap));
                Message message = handler.obtainMessage(0, Bitmap);
                handler.sendMessage(message);
            }
        }.start();
        return null;
    }

    public static Bitmap loadImageFromUrl(String url) {

        Bitmap bm;
        try {  

                URL aURL = new URL(url);  
                URLConnection conn = aURL.openConnection(); 

                conn.connect();  
                InputStream is = null;
                try
                {
                 is= conn.getInputStream();  
                }catch(IOException e)
                {
                     return null;
                }

                BufferedInputStream bis = new BufferedInputStream(is);  

                bm = BitmapFactory.decodeStream(bis);  
                bis.close();  
                is.close();  

           } catch (IOException e) {  
            return null;
           }  

           return  bm;


    }

    public interface ImageCallback {
        public void imageLoaded(Bitmap imageBitmap, DalTours tour);
    }
}

任何帮助都会被提及

4 个答案:

答案 0 :(得分:25)

要解决android.graphics.BitmapFactory.nativeDecodeByteArray中的java.lang.OutOfMemoryError异常,您应该使用以下代码:

BitmapFactory.Options options=new BitmapFactory.Options();// Create object of bitmapfactory's option method for further option use
options.inPurgeable = true; // inPurgeable is used to free up memory while required
Bitmap songImage1 = BitmapFactory.decodeByteArray(thumbnail,0, thumbnail.length,options);//Decode image, "thumbnail" is the object of image file
Bitmap songImage = Bitmap.createScaledBitmap(songImage1, 50 , 50 , true);// convert decoded bitmap into well scalled Bitmap format.

imageview.SetImageDrawable(songImage);

答案 1 :(得分:6)

最后我解决了使用以下线程导致内存不足错误的高分辨率图像问题 Large Image Manipulation

这是我的代码,用于根据您所需的大小下载和缩放图像。

不再需要自定义缩放功能!!!

public static Bitmap loadImageFromUrl(String url) {

        Bitmap bm;
        try {  

                URL aURL = new URL(url);  
                URLConnection conn = aURL.openConnection(); 

                conn.connect();  
                InputStream is = null;
                try
                {
                 is= conn.getInputStream();  
                }catch(IOException e)
                {
                     return null;
                }

                BufferedInputStream bis = new BufferedInputStream(is);  

                bm = BitmapFactory.decodeStream(bis);

                bis.close();  
                is.close();  

           } catch (IOException e) {  
            return null;
           }  

        return  Bitmap.createScaledBitmap(bm,100,100,true);


    }

答案 2 :(得分:3)

你必须recycle位图。位图实现是本机的,因此java对象很小并且是垃圾收集的不良候选者,但仍然分配了内存。塔卡期待Bitmap.recycle()

答案 3 :(得分:-1)

绝对是在内存中为大图像提供位图的情况。如果您反复进行此操作,那么每次都可以回收位图。但是,只是回收并不能保证内存被释放,它几乎没有标记为垃圾回收。所以,作为一个额外的步骤,你也应该处理垃圾收集。

使用此代码;

Bitmap mybitmap = ....; // you are getting the bitmap here
mybitmap.recycle();
System.gc(); // the above recycling may not be enough always