Android OutOfMemory错误(viewpager+;图像视图)

Android OutOfMemory错误(viewpager+;图像视图),android,out-of-memory,android-imageview,android-viewpager,Android,Out Of Memory,Android Imageview,Android Viewpager,我在viewpager中显示了150多张图像,当页面大小超过70的应用程序崩溃时, 所有图像均从网络加载,我已暂停[链接]: 每当翻页次数达到4次时,我就会回收它 用于70页应用程序,占用200 MB内存 我需要你的帮助,怎么处理 我必须用刷卡显示所有页面 我还使用了Runtime.getRuntime().gc() 如果应用程序内存达到50+MB,有没有办法释放内存 提前感谢是否在onCreateView()视图方法中加载图像 这样做时,框架似乎会考虑内存管理需求。我曾尝试在FragmentP

我在viewpager中显示了150多张图像,当页面大小超过70的应用程序崩溃时, 所有图像均从网络加载,我已暂停[链接]:

每当翻页次数达到4次时,我就会回收它

用于70页应用程序,占用200 MB内存

我需要你的帮助,怎么处理

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

我还使用了Runtime.getRuntime().gc()

如果应用程序内存达到50+MB,有没有办法释放内存


提前感谢

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

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

在图纸上标记

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

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;
  }
}
@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];
}
@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;
}
这几乎是我脑子里想不出来的,所以它可能不准确,但它非常接近


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

我认为发生这种情况的原因是内存泄漏,请仔细检查变量,不要对任何大问题使用静态变量,尽可能使用final,使所有成员都是私有的

我建议您进行一次提交(或保存您当前的代码),然后尝试执行我要求的操作,看看是否可以修复它

一个代码示例会让我告诉你,如果你有内存泄漏,也许你可以将代码发布到github或google code之类的地方

一句话:你可以做的每件事都是对的,但是一个变量仍然保存着对你的图片的引用,所以垃圾收集器不能触摸它们

我知道说你有一个内存泄漏伤害,但请不要惊慌,这发生在最好的最好的,因为它很容易发生

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

谢谢

单张

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

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

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

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;
  }
}
@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];
}
@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;
}
然后我在上面的回答中使用了代码

这显然不是完整的代码,它是根据我的实际代码改编的,但它应该能让您很好地了解要做什么以及在哪里做

在图纸上标记

查看代码后,您可以尝试以下操作:

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;
  }
}
@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];
}
@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。

完整的解决方案可以在下面找到,重要的行是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

    }


您是将从网络加载的位图存储在应用程序内存中还是存储在SD卡中?感谢您的快速重播,我将位图存储在SD卡中:文件sdDir=android.os.Environment.getExternalStorageDirectory();cacheDir=新文件(sdDir,context.getString(R.string.cache_dir));你在一页中显示多少图像?每个视图只有一个图像?1页包含1个图像,总页数为150+您是否检查了第70页图像的分辨率是否更高?如果缩放并加载图像,则在每4个图像循环使用时,使用的内存应或多或少保持不变。。为什么仅在第70页中就有200MB?不,我没有在onCreateView()视图方法中加载图像。所有图像都加载到实例化Item PageRadapter中,有没有办法释放(释放)应用程序内存?使用哪些图像我认为你的应用程序当前的结构方式会包含对所有图像的引用,因此你会在某个时候耗尽内存,尤其是在较小的设备上。您需要将图像的创建移动到onCreateView方法,这样框架将只保留三个图像引用,即序列中的前一个图像、当前显示的图像和下一个图像。这些图像将在下一次刷卡时交换,其中一个图像从三个图像列表中脱落,另一个图像将被添加到位。感谢Mark,您能否提供任何示例,说明如何使用onCreateView方法处理图像,是的,让我看看我能为您挖掘什么。感谢提供示例代码,我需要您的更多帮助,我如何使用它查看寻呼机,你能给出完整的示例代码查看寻呼机和片段从不在片段类中使用参数化构造函数我如何检查内存泄漏,需要的变量public rest是privateMark,instanceItem返回什么我在这条语句中遇到错误:return super.instanceItem(container,position);//说明:无法直接为PagerAdapterMark类型调用抽象方法InstanceItem(View,int),我已将示例代码签入github,请查看,它显示空白页,[链接]git@github.com:sheetalsuryan/Samples.gitSheetal,我一直很忙,但今天我会看看你的代码,看看我能想出什么。Sheetal,你缺少strings.xml文件中的cache_dir设置。请更新项目。我不想猜这个值是多少。Sheetal,你能给我写github项目的权限吗,我的用户名是Arcott。Thank.getting ClassCastException当使用View=(View)o;