Outofmemeoryerror(viewpager + imageviews)

时间:2012-02-21 06:16:35

标签: android out-of-memory android-imageview android-viewpager

我在viewpager中显示了150多张图片,当页面大小超过70 app崩溃时, 所有图片都是从网络加载的,我已经暂停[link]:Strange out of memory issue while loading an image to a Bitmap object

当页面滑动达到4时,我正在回收它,

为70页应用程序占用200 MB内存。

我需要你的帮助,如何处理它

我必须用刷卡显示所有页面......

我也使用过Runtime.getRuntime()。gc();

如果app内存达到50+ MB

是释放内存的任何方法

提前致谢

6 个答案:

答案 0 :(得分:18)

完整的解决方案可以在下面找到,重要的行是destroyItem方法中的那些:

private class ContentPagerAdapter extends PagerAdapter {
    @Override
    public void destroyItem(View collection, int position, Object o) {
        View view = (View)o;
        ((ViewPager) collection).removeView(view);
        view = null;
    }

    @Override
    public void finishUpdate(View arg0) {
        // TODO Auto-generated method stub

    }
    @Override
    public int getCount() {
        return ids.length;
    }

    @Override
    public Object instantiateItem(View context, int position) {
        ImageView imageView = new ImageView(getApplicationContext());
        imageView.findViewById(R.id.item_image);
        imageView.setImageBitmap(BitmapFactory.decodeResource(getResources(), ids[position]));

        ((ViewPager) context).addView(imageView);

        return imageView;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view==((ImageView)object);
    }

    @Override
    public void restoreState(Parcelable arg0, ClassLoader arg1) {
        // TODO Auto-generated method stub
    }
    @Override
    public Parcelable saveState() {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public void startUpdate(View arg0) {
        // TODO Auto-generated method stub

    }

答案 1 :(得分:4)

我认为这是因为你有内存泄漏,仔细检查你的变量,不使用静态变量来做任何大事,尽可能使用final,使所有成员都是私有的。

我建议你做一个提交(或保存你当前的代码)然后尝试做我问的问题,看看它是否修复了它。

代码示例会让我告诉你,如果你有内存泄漏,也许你可以在github或谷歌代码上发布代码

底线:您可能正在做的一切正确,但变量仍然保留对图像的引用,因此垃圾收集器无法触及它们。

我知道你说你的内存泄漏很痛,但请不要惊慌,这是最好的,因为它很容易发生。

注意:无论我从网络应用加载的数据有多大,如果处理得当,都不需要超过1个文件的大小。

由于

答案 2 :(得分:1)

Sheetal说道,

查看了您的代码后,您可以尝试以下方法:

@Override
public void destroyItem(View collection, int position, Object o) {
    Log.d("DESTROY", "destroying view at position " + position);
    View view = (View) o;
    ((ViewPager) collection).removeView(view);
    view = null;
}

这应该释放imageView以进行垃圾收集。

答案 3 :(得分:0)

您是否在onCreateView()视图方法中加载图像?

这样做时,框架似乎会照顾内存管理要求。我曾尝试在FragmentPageAdapter中加载我的图像,将它们传递给我预先加载的Fragment构造函数或作为Fragment instaniateItem方法的一部分,但这些都给了我你面临的问题。最后,我传递了将每个图像加载到Fragment构造函数中所需的信息,然后在onCreateView()方法中使用了这些细节。

标记

答案 4 :(得分:0)

Sheetal说道,

我现在没有在我面前的代码,但它应该类似于以下内容:

public class MyFragment extends Fragment {
  private Resources resources;  // I load my images from different resources installed on the device
  private int id;

  public MyFragment() {
    setRetainInstance(true); // this will prevent the app from crashing on screen rotation
  }

  public MyFragment(Resources resources, int id) {
    this();  // this makes sure that setRetainInstance(true) is always called
    this.resources = resources;
    this.id = id;
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ImageView imageView = (ImageView)inflater.infale(R.layout.fragmentview, container, false);
    imageView.setImageBitmap(BitmapFactory.decodeResource(resources, id));

    return imageView;
  }
}

这几乎是我的头脑,所以它可能并不准确,但它非常接近。

如果您需要更多帮助,请不要忘记将此答案标记为帮助您:)。

答案 5 :(得分:0)

Sheetal说道,

根据要求,我使用上面的代码如下:

在我的FragmentActivity中,我在onCreate()方法中执行以下操作:

pager = (ViewPager)findViewById(R.id.pager);
imageAdapter = new MyPagerAdapter(this, pager, theResources, listOfIds.pageBitMapIds);
imageAdapter.setRecentListener(this);
pager.setAdapter(imageAdapter);

然后在我的PagerAdapter中,我执行以下操作:

@Override
public Object instantiateItem(ViewGroup container, int position) {
    MyFragment myFragment = new MyFragment(resources, resourceIds[position], recentListener, position);
    myFragments[position] = myFragment;
    return super.instantiateItem(container, position);
}

@Override
public Fragment getItem(int position) {
    return myFragments[position];
}

然后我使用上一个答案中的代码。

这显然不是完整的代码,它已根据我的实际代码进行了调整,但它应该让你知道该做什么以及在哪里做。

标记