2011-10-12 17 views
9

jestem wyświetlających obrazy w ListView i uzyskiwanie z błędem pamięci ktoś poprowadzi mnie, co jest rozwiązaniem tego problemu tutaj jest mój kodOut Of błąd pamięci z obrazami

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 Metoda

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; 
    } 

Funkcja obraz Skala

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; 

    } 

Obraz Loader Klasa

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); 
    } 
} 

każda pomoc będzie apprecicated

+1

obraz używam jest bardzo duża – UMAR

+0

Jest to kod na Fedor Leniwe Ładowanie obrazów? http://stackoverflow.com/questions/541966/android-how-do-i-do-a-lazy-load-of-images-in-listview/3068012#3068012 –

+0

http: //chrysler-contents.g1curator. com/1313185770.jpg – UMAR

Odpowiedz

6

w końcu rozwiązać ten problem, wysoka rozdzielczość obrazu, który był przyczyną błędu z pamięci za pomocą wątku Large Image Manipulation

i tu jest mój kod do pobierania i skalowanie obrazu w zależności od wymaganej wielkości.

nie jest wymagana żadna niestandardowa funkcja skalowania !!!

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


    } 
3

trzeba recycle bitmapy. Implementacja bitmapy jest natywna, więc obiekt java jest mały i kiepski kandydat do zbierania śmieci java, ale pamięć jest nadal przydzielana. Taka spojrzenie na Bitmap.recycle()

+0

Czy możesz daj mi przykład użycia tego w moim kodzie :( – UMAR

+0

okey ... w celu uruchomienia .. zasada kciuka: Za każdym razem, gdy nie potrzebujesz obiektu bitmapowego, wywołaj Bitmap.recycle W twoim kodzie: w getScaledImage po tobie create bmd, resizedBitmap i actualBitmap nie są już potrzebne .. więc wywołaj resizedBitmap.recycle() i actualBitmap.recycle(). Użyj softreference aby uzyskać pamięć podręczną bitmapy cache imo nie jest dobrym pomysłem (dla natywnej implementacji bitmapy) – Blackbelt

-1

Jest to zdecydowanie przypadek posiadania mapy bitowej dla dużego obrazu w pamięci. Jeśli wielokrotnie robisz tę operację, to dobrze jest ją ponownie wykorzystać za każdym razem. Jednak tylko recykling nie gwarantuje, że pamięć zostanie uwolniona, a jedynie ledwie oznaczona do zbierania śmieci. Tak więc, jako dodatkowy krok, powinieneś także zadbać o zbieranie śmieci.

Użyj tego kodu;

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

System wywołań .gc() nie jest dobrym pomysłem. Przeczytaj te: http://stackoverflow.com/questions/2414105/why-is-it-bad-practice-to-call- system-gc –

24

Rozwiązywania java.lang.OutOfMemoryError wyjątek w android.graphics.BitmapFactory.nativeDecodeByteArray, należy użyć następującego kodu:

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

Świetna odpowiedź !!!! Naprawdę mi to pomogło :) .. – GOLDEE

+2

'inPurgeable' jest przestarzałe, wydaje się, że jest w nowszych wersjach. –

+0

Dziękuję bardzo. ten kod działa dla mnie. – Vrajesh

Powiązane problemy