2012-08-31 4 views
15

W systemie Android 4.1 a, dla mnie, pozornie dziwny błąd występuje w naszej aplikacji. W aplikacji niestandardowy adapter rozszerzający BaseAdapter jest dołączany do widżetu Galeria. Podczas przewijania szybko od lewej do prawej i odwrotnie dostaję FC z komunikatem wyjątek:"Nie można narysować ponownie map bitowych" podczas wyświetlania bitmap w Galerii dołączonej do adaptera

java.lang.IllegalArgumentException: bitmapy nie mogą korzystać z recyklingu

Kod dla getView (..) Metoda jest następująca:

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    ViewHolder viewHolder; 

    if (convertView == null){ 
     // View is not recycled. Inflate the layout. 
     LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     convertView = vi.inflate(R.layout.gallery_image, parent, false); 

     viewHolder = new ViewHolder(); 
     viewHolder.image = (ImageView) convertView.findViewById(R.id.gallery_image); 

     convertView.setTag(viewHolder); 
    } else { 
     viewHolder = (ViewHolder)convertView.getTag(); 
     viewHolder.image.setImageDrawable(null); 
    } 

    imageLoader.displayImage(images.get(position).getFilename(), 
      images.get(position).getUrlThumbnail(), 
      viewHolder.image, 
      Math.round(BitmapUtil.convertDpToPixel(400f, context)), 
      Math.round(BitmapUtil.convertDpToPixel(400f, context))); 

    return convertView; 
} 

Chyba powinienem null gdzieś wyświetlić ImageView, ale nie mogę go uruchomić, aby działał poprawnie. ImageLoader jest (dość) prostą klasą do ładowania obrazów - z LruCache, disk/sdcard lub zdalnie.

+1

czy mógłbyś pokazać kod obrazuLoader - w zasadzie wygląda na to, że w twoim kodzie jest trochę recyklingu mapy bitowej, a potem próbujesz wyświetlić bitmapę (zgodnie z komunikatem o błędzie), ale bez kodu więcej nie może być. powiedział. – Ridcully

Odpowiedz

8

Okazuje się, że ten błąd został wywołany przez wywołanie oldBitmap.recycle() w metodzie entryRemoved(..) w mojej klasie przesłaniającej LruCache. Ponieważ bitmapa może nadal być dołączona do wywołania ImageView recycle() spowoduje problemy.

Jeśli dobrze rozumiem: rozmiar pamięci podręcznej LruCache zostanie ustawiony w jego konstruktorze. Gdy liczba elementów przekroczy ten rozmiar, obiekty będą mogły zostać usunięte, co stanie się, gdy bitmapa nie będzie już powiązana z obrazem.

Wiele przykładów i samouczków w internecie sugeruje, że recycle() powinno być wywoływane w entryRemoved(..), ale z tego, co widzę, jest to złe.

+2

Tak, nie można bezpiecznie założyć, że można wywołać 'recycle()' z 'entryRemoved()'. – CommonsWare

+0

Więc kiedy wywołujesz recycle() w swoim kodzie podczas używania LruCache? – calinL

15

Otrzymujesz ten błąd, ponieważ nie masz dostępu do przetworzonej bitmapy. Jak podaje witryna dla programistów Androida:

Uwolnij obiekt macierzysty powiązany z tą bitmapą i wyczyść odniesienie do danych pikseli. Nie spowoduje to synchronicznego synchronizowania danych pikseli; po prostu pozwala na zbieranie śmieci, jeśli nie ma innych odniesień. Mapa bitowa jest oznaczona jako "martwa", co oznacza, że ​​ wyrzuci wyjątek, jeśli zostanie wywołana funkcja getPixels() lub setPixels(), a niczego nie narysuje. Ta operacja nie może być odwrócona, więc powinna być wywołana tylko wtedy, gdy jesteś pewien, że nie ma dalszych zastosowań dla bitmapy . Jest to wywołanie zaawansowane i zwykle nie musi być wywoływane, , ponieważ normalny proces GC zwolni tę pamięć, gdy nie będzie więcej odniesień do tej bitmapy.

Sugeruję, aby nie poddawać recyklingowi Bitmapy do tego momentu, ponieważ nadal jest do tego przeznaczona. Więc zajrzyj do kodu, gdy zadzwonisz do metody recycle(), a następnie go usuń.

Gdy punkt przychodzi gdzie bitmapy nie musi być stosowany już, to proponuję użyć tej metody, aby wyrzucać Bitmap:

public void disposeBitmap(Bitmap bitmap) { 
     bitmap.recycle(); 
     bitmap = null; 
} 

Mam nadzieję, że to pomaga.

Powiązane problemy