Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android ViewPager Memory leak

I need to create ViewPager in Android with 5 slides, each consists of image and text. I have an array with resources for images:

  private static final int[] images = {R.drawable.tutorial_step_01, R.drawable.tutorial_step_02, R.drawable.tutorial_step_03, R.drawable.tutorial_step_04, R.drawable.tutorial_step_05, R.drawable.tutorial_step_06};

then I create adapter:

@Override
    public Object instantiateItem(ViewGroup container, int position) {

        LinearLayout tv = (LinearLayout) inflater.inflate(R.layout.tut_slide, null);
        TextView title = (TextView) tv.findViewById(R.id.tut_title);
        title.setText(getResources().getText(titles[position]));
        TextView content = (TextView) tv.findViewById(R.id.tut_content);
        ImageView image = (ImageView) tv.findViewById(R.id.tut_image);

        slide_image = BitmapFactory.decodeResource(getResources(), images[position]);
        image.setImageBitmap(slide_image);
        content.setText(getResources().getText(contents[position]));
        ((ViewPager) container).addView(tv, 0);
        return tv;
    }



    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        ((ViewPager) container).removeView((LinearLayout) object);

//
}

trouble is that fact android don't want to collect image after I choose another page. So, after 10-15 changes it goes out with OutOfMemory exception. Then I added to initializung rows

if (slide_image!= null) {
            slide_image.recycle();
            System.gc();
        }

And it's work good! But except one thing: I have black screen instead of first image, whcih is replaced by real one after few flips. So I don't know what to do with such memory leaking

like image 941
Artem Caritas Avatar asked Jul 17 '12 15:07

Artem Caritas


2 Answers

Well, I solved the problem finally. I faced it with a very similar case and as I've seen so many questions related to the same problem, I chose this question as it's yet not answered. The PagerAdapter should call the destroyItem method not only when it surpasses the offLimitScreenPageLimit but also when a screen rotation occurs, but it doesn't, so it has to be forced to do so... to achieve it, you just have to set to null the adapter on the onStop or onDestroy method of the activity.

@Override protected void onDestroy(){
    pager.setAdapter(null);
}

Cheers!

like image 156
Alejandro Navas Avatar answered Oct 20 '22 10:10

Alejandro Navas


It's not clear what you are using but I encountered a similar problem.

I'm assuming you are using FragmentPagerAdapter.

When you scroll away using that adapter, it does not destroy the pages out of view and out of cache. If there is an ImageView in a fragment used by FragmentPageAdapter, OOM is inevitable

Just change the extend of the adapter to

FragmentStatePagerAdapter

This will destroy the fragments not in use and leave more memory free for new fragments.

It's still not perfect, I have found that sometimes I can scroll faster than the garbage collector picks up the destroyed bitmaps, but its pretty damn close.

If I was looking to improve it, I would override destroyItem, and then get the bitmap in use from the imageview and .recycle the bitmap.

Recycle ImageView's Bitmap

like image 41
Pork 'n' Bunny Avatar answered Oct 20 '22 12:10

Pork 'n' Bunny