View Pager with Universal Image Loader Out of Memory Error

自古美人都是妖i 提交于 2019-12-02 19:37:03

Try to apply next suggestions:

  1. Use ImageScaleType.EXACTLY
  2. Enable caching on disc (in display options).
  3. Finally try to use .discCacheExtraOptions(maxImageWidthForDiscCache, maxImageHeightForDiscCache, CompressFormat.PNG, 0);

It's probably not the best implementation to solve it, but it worked for me. Removing the ImageViews is not enough, so I decided to recycle bitmaps in '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;
}

This does not clean the last 3 active pages when you leave the activity, although I hope that GC takes care of them.

Just posting this because this question is coming up on Google when searching for UIL and OOP. I had OOP problems no matter what configuration, what solved all my problems were the two classes RecyclingImageView and RecyclingBitmapDrawable from this sample project.

I also used the same library and had same error. As solution, i created a sparseArray to keep photoView instances. And use it like this:

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

}

And to handle viewPager's listener:

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

Hope this helps...

I used kutothe's implementation from github issues page.

I had this problem when simply setting Uri to ImageView using: iv.setImageURI(Uri.fromFile(imgFile)); I had the same problem with Universal Image Loader, and I even looked for other Image Loaders out there, and found another good one called "Picasso", but it also had the same problem.

So what worked for me is using GestureImageView and setting gesture-image:recycle to true through XML, and load the images with the following code:

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

the reason it was crashing and giving OOM error is that the bitmaps aren't recycled when the image aren't displayed on the screen anymore, hence a memory leak occurs.

If there is another way to recycle the bitmap in the normal ImageView, that would be a better solution.

Hope I helped.

I know it's late, but maybe my answer will save someone's time. After hours and hours of trying to solve this issue (with almost every answer found on stack overflow) I finally solved it with Fresco image library. It'a a lib written by Facebook and it's primary goal is to use memory in efficient way. It's really great and my Out Of Memory Error disappeared. I highly recommend using it.

http://frescolib.org/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!