Viewpager - OutOfMemory - 使用片段

时间:2014-09-07 11:17:31

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

我在StackOverflow中读过这么多线程,但找不到我的问题的解决方案。过去一周我一直试图解决这个问题,但无法弄明白。如果有人可以帮助我,那就太棒了,

这是问题,

我有近50张图片,我使用ViewPager和Fragments让用户在图片中滑动。所有图像均为250 * 350维,每张图像不超过20KB。在Swyping 30th-35th image上我得到OutOfMemory异常..这是堆栈跟踪,

09-07 16:30:09.126: E/MessageQueue-JNI(1023): java.lang.OutOfMemoryError
09-07 16:30:09.126: E/MessageQueue-JNI(1023):   at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
09-07 16:30:09.126: E/MessageQueue-JNI(1023):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:683)
09-07 16:30:09.126: E/MessageQueue-JNI(1023):   at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:513)
09-07 16:30:09.126: E/MessageQueue-JNI(1023):   at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:541)
09-07 16:30:09.126: E/MessageQueue-JNI(1023):   at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:571)

以下是代码MyGallery.java,

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        List<Fragment> fragments = getFragments();

        pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
        ViewPager pager = (ViewPager) findViewById(R.id.viewpager);
        pager.setOffscreenPageLimit(2);
        pager.setAdapter(pageAdapter);
     }



private List<Fragment> getFragments() {
    List<Fragment> fList = new ArrayList<Fragment>();
    String picture_book = "";
    for (int i = 1; i <= 50; i++) {
        picture_book = "picture" + i;
        fList.add(MyGallery_Fragment.newInstance(picture_book));
    }
    return fList;
}

private class MyPageAdapter extends FragmentStatePagerAdapter {
    private List<Fragment> fragments;

    public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        this.fragments = fragments;
    }

    @Override
    public Fragment getItem(int position) {
        return this.fragments.get(position);
    }

    @Override
    public int getCount() {
        return this.fragments.size();
    }
}

这是MyGaller_Fragment类,

public static final MyGallery_Fragment newInstance(String picture) {

        MyGallery_Fragment f = new MyGallery_Fragment();
        contextForDialog = f.getActivity();
        Bundle bdl = new Bundle();
        bdl.putString("picture", picture);

        f.setArguments(bdl);
        return f;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        context = activity.getApplicationContext();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        picture = getArguments().getString("picture");

        View v = inflater
                .inflate(R.layout.mygallery_fragment, container, false);


        picture_img = (ImageView) v.findViewById(R.id.picture_iv);
        picture_resID = getResources().getIdentifier(picture, "drawable",
                context.getPackageName());


        picture_biticon = BitmapFactory.decodeResource(getResources(),
                picture_resID);
        picture_img.setImageBitmap(picture_biticon);

        return v;
    }
 }

这就是我试过的,

  1. 我正在使用FragmentPagerAdapter并更改为FragmentStatePagerAdapter,如上所述here ..我认为FragmentStatePagerAdapter只是将片段的视图直接保留,当前显示的项目的权利并自动销毁其他项目..但这并没有解决问题,

  2. 我甚至将setOffScreenPageLimit设置为2,这样旧的碎片就会被破坏..但这也没有解决。

  3. 我在分配值后尝试销毁Bitmap,但遇到了同样的错误。

  4. 我也在MyGallery_Fragment类中尝试了这段代码,

    @Override public void onDestroy() { super.onDestroy(); Drawable drawable = picture_img.getDrawable(); if (drawable instanceof BitmapDrawable) { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; picture_biticon = bitmapDrawable.getBitmap(); picture_biticon.recycle(); } }

  5. 我在Note II中对应用程序进行了测试,它在第30个第35个图像滑动之间显示outofmemory,但相同的代码在我新购买的Moto E中正常工作。

    < / LI>

    如果有人能帮助我解决这个问题会很棒。

2 个答案:

答案 0 :(得分:1)

存储这么多碎片是个坏主意 - 你不应该这样做。 View寻呼机为动画目的缓存邻居,这就足够了。而不是碎片。列表中,您应该考虑存储构建特定视图所需的模型列表,并在适配器中动态创建片段。

其他建议:

三星设备处理内存的方式与其他设备不同,我在S3和S4上遇到了类似的问题。此外,您应该知道视图寻呼机默认加载当前片段的邻居,因此如果您将屏幕限制设置为2,这意味着viewpager还将从当前一个加载两个片段,在右侧加载两个片段,因此您应该考虑保留默认值价值(1)。

关于文件大小 - 如果它在文件中是30KB并不意味着它将在图形卡内存中使用相同的数量 - 它通常更多。您应该考虑在运行时重新调整它们,然后再按Vino提到的那样将其推送到视图中。您也可以尝试在清单应用程序节点中设置android:largeHeap =“true”。

答案 1 :(得分:0)

有一篇关于在developer.android.com网站上加载位图的文章。您可以将其视为最佳实践。您可以在http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

找到它

它讨论了加载位图的不同机制。你考虑过那些吗?

查看代码,将屏幕外限制设置为2.但同时,您将创建50个片段实例并将其添加到列表中。我认为你的代码看起来应该是(未经测试的代码)

public MyPageAdapter(FragmentManager fm) {
    super(fm);
}

@Override
    public Fragment getItem(int position) {
        String picture_book = "picture" + i;
        return MyGallery_Fragment.newInstance(picture_book);
    }

    @Override
    public int getCount() {
        return 50;
    }