View Pager with Universal Image Loader Out of Memory Error
Nie jestem pewien, czy ViewPager z Universal Image Loader może / powinien być używany jako alternatywa dla interfejsu galerii, ponieważ napotkałem błąd braku pamięci podczas ładowania obrazów z karty SD i przeglądania ich w trybie pełnoekranowym. Bez względu na liczbę, działa to dobrze z GridView, ale podczas przeglądania obrazów w widoku Pager, każda bitmapa pożera dużo pamięci i po 10 lub tak obrazów, daje błąd out of memory.
Widziałem prawie wszystkie pytania, które zostały tutaj opublikowane, dotyczyły błędu Out of Memory podczas pracy z Universal Image Loader i w każdym z nich wystąpił błąd konfiguracji jako przyczyna.
Nie wiem, czy używam niewłaściwych konfiguracji lub co, ale zmarnowałem na to dużo czasu i trochę utknąłem, każda pomoc/porady będą mile widziane.
Konfiguracje dla ImageLoader:
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
.memoryCache(new WeakMemoryCache())
.denyCacheImageMultipleSizesInMemory()
.discCacheFileNameGenerator(new Md5FileNameGenerator())
.imageDownloader(new ExtendedImageDownloader(getApplicationContext()))
.tasksProcessingOrder(QueueProcessingType.LIFO)
// .enableLogging() // Not necessary in common
.build();
Opcje wyświetlania obrazu to:
options = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.image_for_empty_url)
.resetViewBeforeLoading()
.imageScaleType(ImageScaleType.IN_SAMPLE_INT)
.bitmapConfig(Bitmap.Config.RGB_565)
.displayer(new FadeInBitmapDisplayer(300))
.build();
Jestem używając przykładowego projektu, który został podany z biblioteką, ale te ustawienia też nie działają, po prostu zawiesza się po pewnym czasie. Domyślam się, że istnieje konkretna funkcja zwrotna, w której muszę przetwarzać bitmapy z widoków, z których nie są widoczne.
EDIT: wiem, że to wyciek pamięci, widoki, które nie są widoczne, są niszczone, kiedy powinny być, ale pamięć nie jest uwalniana tak, jak powinna. Heres implementacji wywołania zwrotnego destroyItem, postępując zgodnie z wskazówkami podanymi w różnych pytania, ale nadal nie można znaleźć wycieku pamięci.
@Override
public void destroyItem(View container, int position, Object object) {
// ((ViewPager) container).removeView((View) object);
Log.d("DESTROY", "destroying view at position " + position);
View view = (View)object;
((ViewPager) container).removeView(view);
view = null;
}
7 answers
Spróbuj zastosować następne sugestie:
- Użyj
ImageScaleType.EXACTLY
- Włącz buforowanie na dysku (w opcjach wyświetlania).
- Wreszcie spróbuj użyć
.discCacheExtraOptions(maxImageWidthForDiscCache, maxImageHeightForDiscCache, CompressFormat.PNG, 0);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-24 16:13:56
To prawdopodobnie nie jest najlepsza implementacja do rozwiązania tego problemu, ale u mnie zadziałało. Usunięcie Imageviewów nie wystarczy, więc zdecydowałem się na recykling bitmap w 'destroyItem':
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
View view = (View) object;
ImageView imageView = (ImageView) view.findViewById(R.id.image);
if (imageView != null) {
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
bitmap.recycle();
bitmap = null;
}
((ViewPager) container).removeView(view);
view = null;
}
To nie czyści ostatnich 3 aktywnych stron po opuszczeniu aktywności, chociaż mam nadzieję, że GC się nimi zajmie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-12 17:31:21
Po prostu zamieszczam to, ponieważ to pytanie pojawia się w Google podczas wyszukiwania UIL i OOP. Miałem problemy z OOP bez względu na konfigurację, co rozwiązało wszystkie moje problemy były dwie klasy RecyclingImageView
i RecyclingBitmapDrawable
z ten przykładowy projekt.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-26 08:10:46
Używałem tej samej biblioteki i miałem ten sam błąd. Jako rozwiązanie stworzyłem sparseArray, aby zachować instancje photoView. I używaj go tak:
private SparseArray<PhotoView> photoViewHolder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
photoViewHolder = new SparseArray<PhotoView>();
...
}
private class GalleryPagerAdapter extends PagerAdapter {
@Override
public View instantiateItem(ViewGroup container, int position) {
PhotoView photoView = new PhotoView(container.getContext());
ImageHolder holder = new ImageHolder();
holder.position = position;
holder.loaded = false;
photoView.setTag(holder);
photoViewHolder.put(position, photoView);
// I used LazyList loading
loader.DisplayImage(items.get(position), photoView);
// Now just add PhotoView to ViewPager and return it
container.addView(photoView, LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
return photoView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
photoViewHolder.remove(position);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
I do obsługi słuchacza viewpagera:
pager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageScrollStateChanged(int position) {
}
@Override
public void onPageScrolled(int position, float arg1, int arg2) {
}
@Override
public void onPageSelected(int position) {
if(photoViewHolder.get(position) != null) {
ImageHolder holder = (ImageHolder)photoViewHolder.get(position).getTag();
// Do something...
}
}
});
Mam nadzieję, że to pomoże...Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-07 13:48:54
Użyłem implementacji kutothe ze strony github issues.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-21 14:32:33
Miałem taki problem gdy ustawiałem Uri na ImageView
używając: iv.setImageURI(Uri.fromFile(imgFile));
Miałem ten sam problem z Universal Image Loader, a nawet Szukałem innych Image Loaderów i znalazłem inny dobry o nazwie " Picasso ", ale miał też ten sam problem.
Więc to, co mi się udało, to użycie GestureImageView
i ustawienie gesture-image:recycle
na true poprzez XML i załadowanie obrazów następującym kodem:
Drawable yourDrawable = null;
try {
InputStream inputStream = getActivity().getContentResolver().openInputStream(Uri.fromFile(img));
yourDrawable = Drawable.createFromStream(inputStream, Uri.fromFile(img).toString() );
inputStream.close();
} catch (FileNotFoundException e) {
yourDrawable = getResources().getDrawable(R.drawable.ic_launcher);
} catch (IOException e) {
e.printStackTrace();
}
if (yourDrawable != null)
iv.setImageDrawable(yourDrawable);
Powodem awarii i wystąpienia błędu OOM jest to, że bitmapy nie są poddawane recyklingowi, gdy obraz nie jest już wyświetlany na ekranie, w związku z czym występuje wyciek pamięci.
Jeśli istnieje inny sposób recyklingu bitmapy w normalnym ImageView
, byłoby to lepszym rozwiązaniem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-10 10:29:25
Wiem, że jest późno, ale może moja odpowiedź zaoszczędzi komuś czasu. Po wielu godzinach prób rozwiązania tego problemu (prawie każda odpowiedź znajduje się na stack overflow) w końcu rozwiązałem go z fresco image library. To lib napisany przez Facebook i jego głównym celem jest efektywne wykorzystanie pamięci. Jest naprawdę świetny i mój błąd z pamięci zniknął. Gorąco polecam korzystanie z niego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-21 18:35:01