Android ViewPager内存泄漏

时间:2012-07-17 15:40:07

标签: android memory-leaks bitmap android-viewpager

我需要在Android中使用5张幻灯片创建ViewPager,每张幻灯片都包含图片和文字。我有一个包含图像资源的数组:

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

然后我创建适配器:

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

//
        }

麻烦的是,在我选择另一个页面之后,android不想收集图像。因此,在10-15次更改后,它会出现OutOfMemory异常。然后我添加到初始行

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

这很好用!但除了一件事:我有黑色屏幕而不是第一张图像,在几次翻转之后被真正的图像取代。所以我不知道如何处理这种内存泄漏

4 个答案:

答案 0 :(得分:4)

好吧,我终于解决了这个问题。我面对的是一个非常相似的案例,而且我看到很多与同一问题相关的问题,我选择了这个问题,因为它还没有得到回答。 PagerAdapter方法不仅要在超出destroyItem时调用offLimitScreenPageLimit方法,而且还要在屏幕旋转时调用onStop方法,但它不会被调用,因此必须强制执行所以......为了实现它,你只需要在活动的onDestroy@Override protected void onDestroy(){ pager.setAdapter(null); } 方法上设置为null适配器。

{
abc_1 |    "warnings" : [],
abc_1|    "diskperms" : {},
abc_1 |    "diskspace" : {},
abc_1 |    "data" : [],
abc_1 |    "log" : [
abc_1 |       "[ERROR] [28] Local-disk package '/packages/xyz.tar.gz' does not exist on disk."
abc_1 |    ],
abc_1 |    "http_info" : {},
abc_1 |    "result" : {
abc_1 |       "msg" : "Local-disk package '/packages/xyz.tar.gz' does not exist on disk.",
abc_1 |       "status" : 1
abc_1 |    },
abc_1 |    "state" : {}
abc_1 | }
dockerzookeeper1_abc_1 exited with code 1
Gracefully stopping... (press Ctrl+C again to force)
Stopping dockerzookeeper1_zookeeper_1...

干杯!

答案 1 :(得分:1)

目前尚不清楚你在使用什么,但我遇到了类似的问题。

我假设您正在使用FragmentPagerAdapter。

使用该适配器滚动时,它不会破坏视图外的页面和缓存。如果FragmentPageAdapter使用的片段中有ImageView,则OOM是不可避免的

只需将适配器的扩展名更改为

即可

FragmentStatePagerAdapter

这会破坏未使用的碎片,并为新碎片留出更多内存。

它仍然不完美,我发现有时候我可以滚动得比垃圾收集器拾取被破坏的位图更快,但它非常接近。

如果我想改进它,我会覆盖destroyItem,然后从imageview获取位图并使用.recycle位图。

Recycle ImageView's Bitmap

答案 2 :(得分:0)

该行为不应与内存泄漏有关。看起来它与您在viewpager更新生命周期中何时以及如何回收位图有关。尝试在初始化的某个时刻手动调用onPageSelected()或notifyDatasetChanged()。

此解决方案可能无法完全解决问题,但请尝试一下。你的解释很难说清楚。

答案 3 :(得分:0)

就我而言,我在ViewPager中有31页。我用这个:

 @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {

        if(dbCon!=null)
            dbCon.close();

        ViewPager viewPager = (ViewPager)container;
        View view = (View) object;
        viewPager.removeView(view);
    }

,一切正常。 Alhamdulillah。