android - FragmentStatePagerAdapter OutOfMemoryError

标签 android out-of-memory universal-image-loader android-pageradapter fragmentstatepageradapter

我在我正在开发的应用程序中遇到了 OutOfMemoryErrors,我很难弄清楚如何修复它以及到底是什么问题。我正在使用 FragmentStatePagerAdapter,因为这似乎是最佳/推荐的替代方案。我也在使用 Universal Image Loader v.1.8.4 .发生的情况是,当您翻阅 View 时,堆会增长并最终耗尽内存。这是一个小示例输出:

05-06 14:38:23.096: D/dalvikvm(29322): GC_CONCURRENT freed 187K, 5% free 7532K/7868K, paused 7ms+13ms, total 37ms
05-06 14:38:23.176: D/dalvikvm(29322): GC_FOR_ALLOC freed 96K, 4% free 7656K/7920K, paused 17ms, total 17ms
05-06 14:38:23.206: D/dalvikvm(29322): GC_FOR_ALLOC freed <1K, 4% free 8234K/8500K, paused 15ms, total 15ms
05-06 14:38:23.246: D/dalvikvm(29322): GC_CONCURRENT freed 4K, 3% free 8262K/8500K, paused 5ms+5ms, total 31ms
05-06 14:38:23.276: D/dalvikvm(29322): GC_FOR_ALLOC freed 29K, 3% free 8289K/8500K, paused 20ms, total 25ms
05-06 14:38:23.286: D/dalvikvm(29322): GC_FOR_ALLOC freed <1K, 3% free 9342K/9556K, paused 15ms, total 15ms
05-06 14:38:23.316: D/dalvikvm(29322): GC_CONCURRENT freed 27K, 3% free 9327K/9556K, paused 3ms+2ms, total 22ms
05-06 14:38:24.626: D/dalvikvm(29322): GC_FOR_ALLOC freed 83K, 3% free 9462K/9696K, paused 15ms, total 16ms
05-06 14:38:24.646: D/dalvikvm(29322): GC_FOR_ALLOC freed 3K, 3% free 10201K/10440K, paused 16ms, total 16ms
05-06 14:38:24.666: D/dalvikvm(29322): GC_CONCURRENT freed 3K, 3% free 10214K/10440K, paused 3ms+3ms, total 26ms
05-06 14:38:24.976: D/dalvikvm(29322): GC_FOR_ALLOC freed 68K, 3% free 10291K/10508K, paused 16ms, total 17ms
05-06 14:38:24.986: D/dalvikvm(29322): GC_FOR_ALLOC freed <1K, 2% free 11297K/11516K, paused 15ms, total 15ms
05-06 14:38:25.016: D/dalvikvm(29322): GC_CONCURRENT freed 8K, 2% free 11305K/11516K, paused 3ms+4ms, total 24ms
05-06 14:38:25.346: D/dalvikvm(29322): GC_CONCURRENT freed 74K, 2% free 12458K/12680K, paused 2ms+3ms, total 23ms
05-06 14:38:25.976: D/dalvikvm(29322): GC_FOR_ALLOC freed 151K, 3% free 13485K/13792K, paused 22ms, total 22ms
05-06 14:38:26.276: D/dalvikvm(29322): GC_CONCURRENT freed 95K, 2% free 15384K/15636K, paused 3ms+3ms, total 26ms
05-06 14:38:27.196: D/dalvikvm(29322): GC_FOR_ALLOC freed 222K, 3% free 17111K/17484K, paused 24ms, total 24ms
05-06 14:38:28.446: D/dalvikvm(29322): GC_FOR_ALLOC freed 247K, 2% free 19784K/20180K, paused 22ms, total 22ms
05-06 14:38:29.396: D/dalvikvm(29322): GC_FOR_ALLOC freed 248K, 2% free 23137K/23540K, paused 23ms, total 24ms
05-06 14:38:30.976: D/dalvikvm(29322): GC_FOR_ALLOC freed 391K, 2% free 27770K/28308K, paused 29ms, total 29ms
05-06 14:38:33.366: D/dalvikvm(29322): GC_CONCURRENT freed 516K, 2% free 33964K/34628K, paused 3ms+6ms, total 45ms
05-06 14:38:36.126: D/dalvikvm(29322): GC_FOR_ALLOC freed 608K, 2% free 41164K/41920K, paused 37ms, total 37ms
05-06 14:38:38.396: D/dalvikvm(29322): GC_CONCURRENT freed 598K, 2% free 48739K/49484K, paused 4ms+10ms, total 59ms
05-06 14:38:41.496: D/dalvikvm(29322): GC_CONCURRENT freed 723K, 2% free 56176K/57044K, paused 2ms+13ms, total 71ms
05-06 14:38:41.496: D/dalvikvm(29322): WAIT_FOR_CONCURRENT_GC blocked 62ms
05-06 14:38:45.176: I/dalvikvm-heap(29322): Clamp target GC heap from 69.393MB to 64.000MB
05-06 14:38:45.176: D/dalvikvm(29322): GC_FOR_ALLOC freed 597K, 2% free 62724K/63476K, paused 56ms, total 56ms
05-06 14:38:45.936: I/dalvikvm-heap(29322): Clamp target GC heap from 71.379MB to 64.000MB
05-06 14:38:45.936: D/dalvikvm(29322): GC_FOR_ALLOC freed 216K, 1% free 64758K/65412K, paused 50ms, total 50ms
05-06 14:38:45.996: I/dalvikvm-heap(29322): Clamp target GC heap from 71.338MB to 64.000MB
05-06 14:38:45.996: D/dalvikvm(29322): GC_BEFORE_OOM freed 43K, 2% free 64714K/65412K, paused 60ms, total 60ms
05-06 14:38:46.336: I/dalvikvm-heap(29322): Clamp target GC heap from 71.462MB to 64.000MB
05-06 14:38:46.336: D/dalvikvm(29322): GC_FOR_ALLOC freed 139K, 2% free 64841K/65500K, paused 52ms, total 52ms
05-06 14:38:46.396: I/dalvikvm-heap(29322): Clamp target GC heap from 71.462MB to 64.000MB
05-06 14:38:46.396: D/dalvikvm(29322): GC_BEFORE_OOM freed <1K, 2% free 64840K/65500K, paused 62ms, total 62ms

首先,是的,我在 stackoverflow 和其他网站上做了很多挖掘工作,试图找出问题所在。我已经尝试了各种回收位图的解决方案,使用 unbindDrawables,并尝试在 PagerAdapter 的 destroyItem() 中删除 View /回收位图……仅举几例。这些都不适合我(如果需要,我可以提供有关我所做工作的更多详细信息)。

因此,简而言之,我可以使用 this example 的修改版本重现我的问题(来自谷歌开发者网站)。我对其进行了一些修改以与 Universal Image Loader v.1.8.4 一起使用并且还使布局更复杂一些,以在某种程度上模仿我正在使用的应用程序中的内容。我更改布局的原因是,如果您使布局非常简单并且仅包含图像和一些文本字段,那么一切似乎都可以正常工作。当布局变得更复杂并且当您开始向适配器添加更多页面时,您会开始遇到 OOM 错误。但是,我不确定这是布局或 UIL 的问题...继续阅读...

我在 Eclipse 中运行了 MAT,这是它在唯一的 Leak Suspects 报告(只有 1 个问题)下的内容:

One instance of "com.example.android.animationsdemo.ScreenSlideActivity$ScreenSlidePagerAdapter"
loaded by "dalvik.system.PathClassLoader @ 0x42124098" occupies 56,171,048 (86.62%) bytes.
The memory is accumulated in one instance of "java.lang.Object[]" loaded by "<system class loader>".

Keywords
java.lang.Object[]
dalvik.system.PathClassLoader @ 0x42124098
com.example.android.animationsdemo.ScreenSlideActivity$ScreenSlidePagerAdapter

如果您随后查看 Dominator Tree 并展开 ScreenSlidePagerAdapter,它会显示以下 59 个条目中的 25 个:

> java.util.ArrayList @ 0x4216ccf0
    > java.lang.Object[60] @ 0x44b07d8
        > android.app.Fragment$SavedState @ 0x439bd038

我不是这个工具的专家,我对 Android 和一般的开发还很陌生,但看起来适配器的保存状态没有被正确清除,这就是导致 OOM 问题的原因(它正在保存整个 View ,而不仅仅是位图)。但是,我一直无法弄清楚如何清除/释放/销毁/无论保存的状态数据是什么,或者我是否在其他地方做错了什么。我确实遇到过一篇帖子说尝试使用 .setSaveEnabled(false),但这没有任何区别,我仍然遇到 OOM 错误。我什至尝试为适配器重写 saveState() 并返回 null,但这也没有什么不同。

以下是相关的代码/配置信息,有望回答大部分问题:

对于 UIL,我只使用默认配置,因为更改似乎没有什么不同:

imageLoader.init(ImageLoaderConfiguration.createDefault(this));

屏幕滑动 Activity :

public class ScreenSlideActivity extends FragmentActivity {
    /**
     * The number of pages (wizard steps) to show in this demo.
     */
    private static final String[] IMAGES = Constants.IMAGES;

    /**
     * The pager widget, which handles animation and allows swiping horizontally to access previous
     * and next wizard steps.
     */
    private ViewPager mPager;

    /**
     * The pager adapter, which provides the pages to the view pager widget.
     */
    private PagerAdapter mPagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_screen_slide);

        // Instantiate a ViewPager and a PagerAdapter.
        mPager = (ViewPager) findViewById(R.id.pager);
        mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager(), IMAGES);

        mPager.setSaveEnabled(false); // <--- THIS DOESN'T APPEAR TO MAKE ANY DIFFERENCE

        mPager.setAdapter(mPagerAdapter);
        mPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                // When changing pages, reset the action bar actions since they are dependent
                // on which page is currently active. An alternative approach is to have each
                // fragment expose actions itself (rather than the activity exposing actions),
                // but for simplicity, the activity provides the actions in this sample.
                invalidateOptionsMenu();
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.activity_screen_slide, menu);

        menu.findItem(R.id.action_previous).setEnabled(mPager.getCurrentItem() > 0);

        // Add either a "next" or "finish" button to the action bar, depending on which page
        // is currently selected.
        MenuItem item = menu.add(Menu.NONE, R.id.action_next, Menu.NONE,
                (mPager.getCurrentItem() == mPagerAdapter.getCount() - 1)
                        ? R.string.action_finish
                        : R.string.action_next);
        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                // Navigate "up" the demo structure to the launchpad activity.
                // See http://developer.android.com/design/patterns/navigation.html for more.
                NavUtils.navigateUpTo(this, new Intent(this, MainActivity.class));
                return true;

            case R.id.action_previous:
                // Go to the previous step in the wizard. If there is no previous step,
                // setCurrentItem will do nothing.
                mPager.setCurrentItem(mPager.getCurrentItem() - 1);
                return true;

            case R.id.action_next:
                // Advance to the next step in the wizard. If there is no next step, setCurrentItem
                // will do nothing.
                mPager.setCurrentItem(mPager.getCurrentItem() + 1);
                return true;
        }

        return super.onOptionsItemSelected(item);
    }

    /**
     * A simple pager adapter that represents 5 {@link ScreenSlidePageFragment} objects, in
     * sequence.
     */
    private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
        String[] mImages;
        public ScreenSlidePagerAdapter(FragmentManager fm, String[] images) {
            super(fm);
            this.mImages = images;
        }

        @Override
        public Fragment getItem(int position) {
            return ScreenSlidePageFragment.create(position, mImages);
        }

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

ScreenSlidePageFragment,由上述 Activity 调用:

public class ScreenSlidePageFragment extends Fragment {

    // Universal Image Loader
    private DisplayImageOptions mOptions;
    protected ImageLoader mImageLoader = ImageLoader.getInstance();

    /**
     * The argument key for the page number this fragment represents.
     */
    public static final String ARG_PAGE = "page";

    public static final String ARG_IMAGES = "images";

    /**
     * The fragment's page number, which is set to the argument value for {@link #ARG_PAGE}.
     */
    private int mPageNumber;
    private String[] mImages;

    /**
     * Factory method for this fragment class. Constructs a new fragment for the given page number.
     */
    public static ScreenSlidePageFragment create(int pageNumber, String[] images) {
        ScreenSlidePageFragment fragment = new ScreenSlidePageFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_PAGE, pageNumber);
        args.putStringArray(ARG_IMAGES, images);
        fragment.setArguments(args);
        return fragment;
    }

    public ScreenSlidePageFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPageNumber = getArguments().getInt(ARG_PAGE);
        mImages = getArguments().getStringArray(ARG_IMAGES);

        mOptions = new DisplayImageOptions.Builder()
        .showImageForEmptyUri(R.drawable.ic_empty)
        .showImageOnFail(R.drawable.ic_error)
        .resetViewBeforeLoading()
        .cacheOnDisc()
        .imageScaleType(ImageScaleType.EXACTLY)
        .bitmapConfig(Bitmap.Config.RGB_565)
        .displayer(new SimpleBitmapDisplayer())
        .build();

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // Inflate the layout containing a title and body text.
        ViewGroup rootView = (ViewGroup) inflater
                .inflate(R.layout.fragment_screen_slide_page, container, false);

        // Set the title view to show the page number.
        ((TextView) rootView.findViewById(android.R.id.text1)).setText(
                getString(R.string.title_template_step, mPageNumber + 1));
        displayImageFile(rootView);
        return rootView;
    }

    private void displayImageFile (ViewGroup view) {

        ImageView imageView = (ImageView) view.findViewById(R.id.item_image_to_display);

        mImageLoader.displayImage(mImages[mPageNumber], imageView, mOptions);

    }

    /**
     * Returns the page number represented by this fragment object.
     */
    public int getPageNumber() {
        return mPageNumber;
    }
}

ScreenSlideActivity 使用的Layout activity_screen_slide.xml 和ViewPager 的id:

<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

ScreenSlidePageFragment 使用的 fragment_screen_slide_page.xml:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/content"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <!-- Dummy content. -->

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp" >

        <TextView
            android:id="@android:id/text1"
            style="?android:textAppearanceLarge"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="16dp"
            android:textStyle="bold" />

        <TextView
            style="?android:textAppearanceMedium"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:lineSpacingMultiplier="1.2"
            android:text="@string/lorem_ipsum" />

        <TextView
            android:id="@+id/item_details"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:gravity="center_vertical"
            android:text="@string/item_details" />

        <TextView
            android:id="@+id/item_type_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="@string/item_type_text" />

        <Spinner
            android:id="@+id/item_type"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:prompt="@string/item_type_text"
            android:text="@string/item_type" />

        <TextView
            android:id="@+id/item_name_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="@string/item_name_text" />

        <EditText
            android:id="@+id/item_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:gravity="top|left"
            android:hint="@string/item_name"
            android:inputType="text" />

        <TextView
            android:id="@+id/item_text_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="@string/item_text_text" />

        <EditText
            android:id="@+id/item_text"
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:layout_marginLeft="10dp"
            android:ems="10"
            android:gravity="top|left"
            android:hint="@string/item_text"
            android:inputType="textMultiLine" />

        <TextView
            android:id="@+id/sound_edit_text"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:gravity="center_vertical"
            android:text="@string/sound_edit" />

        <ImageView
            android:id="@+id/item_add_audio"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:contentDescription="@string/cd_image_add_button"
            android:src="@android:drawable/ic_menu_add" />

        <TextView
            android:id="@+id/recording_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginBottom="20dp"
            android:layout_marginTop="20dp"
            android:text="@string/recording_text" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:padding="16dp" >

            <ImageButton
                android:id="@+id/item_play_audio"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="33"
                android:contentDescription="@string/cd_play_sound_button"
                android:soundEffectsEnabled="false"
                android:src="@drawable/play" />

            <ImageButton
                android:id="@+id/item_stop_audio"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="34"
                android:contentDescription="@string/cd_stop_sound_button"
                android:soundEffectsEnabled="false"
                android:src="@drawable/stop" />

            <ImageButton
                android:id="@+id/item_record_audio"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="33"
                android:contentDescription="@string/cd_record_sound_button"
                android:soundEffectsEnabled="false"
                android:src="@drawable/rec" />
        </LinearLayout>

        <TextView
            android:id="@+id/edit_image"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:gravity="center_vertical"
            android:text="@string/edit_image" />

        <TextView
            android:id="@+id/image_replace_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginBottom="10dp"
            android:layout_marginTop="10dp"
            android:text="@string/image_replace"
            android:visibility="visible" />

        <ImageView
            android:id="@+id/item_image_to_display"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:adjustViewBounds="true"
            android:contentDescription="@string/cd_item_image" />

        <TextView
            android:id="@+id/item_image_effect_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="@string/item_image_effect_text" />

        <Spinner
            android:id="@+id/item_image_effect"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp" />

        <TextView
            android:id="@+id/item_text_color_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="@string/item_text_color_text" />

        <Spinner
            android:id="@+id/item_text_color"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp" />

        <TextView
            android:id="@+id/item_text_size_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="@string/item_text_size_text" />

        <EditText
            android:id="@+id/item_text_size"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:hint="@string/item_text_size"
            android:inputType="number" />

        <TextView
            android:id="@+id/item_text_style_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="@string/item_text_style_text" />

        <Spinner
            android:id="@+id/item_text_style"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp" />

        <TextView
            android:id="@+id/item_text_alignment_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="@string/item_text_alignment_text" />

        <Spinner
            android:id="@+id/item_text_alignment"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp" />

        <TextView
            android:id="@+id/item_background_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="@string/item_background_text" />

        <Spinner
            android:id="@+id/item_background"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp" />
    </LinearLayout>

</ScrollView>

此外,这是我遇到的 OOM 错误:

05-06 16:37:59.656: E/ImageLoader(3175): null
05-06 16:37:59.656: E/ImageLoader(3175): java.lang.OutOfMemoryError
05-06 16:37:59.656: E/ImageLoader(3175):    at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
05-06 16:37:59.656: E/ImageLoader(3175):    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:529)
05-06 16:37:59.656: E/ImageLoader(3175):    at com.nostra13.universalimageloader.core.ImageDecoder.decode(ImageDecoder.java:82)
05-06 16:37:59.656: E/ImageLoader(3175):    at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.decodeImage(LoadAndDisplayImageTask.java:270)
05-06 16:37:59.656: E/ImageLoader(3175):    at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.tryLoadBitmap(LoadAndDisplayImageTask.java:224)
05-06 16:37:59.656: E/ImageLoader(3175):    at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.run(LoadAndDisplayImageTask.java:149)
05-06 16:37:59.656: E/ImageLoader(3175):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
05-06 16:37:59.656: E/ImageLoader(3175):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
05-06 16:37:59.656: E/ImageLoader(3175):    at java.lang.Thread.run(Thread.java:856)

为了消除 OOM 错误,我可以查看/更改什么?

最佳答案

原来是 unbindDrawables 最终解决了我的问题。不确定我之前做错了什么(太晚了......???;-)),但我遇到了this post它解决了我的问题。上述帖子与我看到的其他一些 unbindDrawable 帖子略有不同,我没有收到任何 java.lang.UnsupportedOperationException: removeAllViews() is not supported in AdapterView 错误,就像我在我已经尝试了一些其他版本(这对我来说可能只是一些愚蠢的事情)。

我在 ScreenSildePageFragment 类中实现了以下内容,它解决了我的 OOM 问题:

@Override
protected void onDestroy()
{
        super.onDestroy();

        unbindDrawables(mRootView.findViewById(R.id.content)); // <---This should be the ID of this fragments (ScreenSlidePageFragment) layout
}

private void unbindDrawables(View view)
{
        if (view.getBackground() != null)
        {
                view.getBackground().setCallback(null);
        }
        if (view instanceof ViewGroup && !(view instanceof AdapterView))
        {
                for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++)
                {
                        unbindDrawables(((ViewGroup) view).getChildAt(i));
                }
                ((ViewGroup) view).removeAllViews();
        }
}

注意:如帖子中所述,在 onDestroy() 中调用 unbindDrawables() 后,我没有使用 System.gc();。在我测试的设备上使用它似乎没有任何真正的区别,我认为让系统管理垃圾收集可能更好。

关于android - FragmentStatePagerAdapter OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16409020/

相关文章:

android - 通过 Android Universal Image Loader 缓存所有图像

android - “通用图像加载器”丢失了我的 ImageView 的参数(大小和位置)

android - 可见性设置为 "gone"的 View 是否是测量和布局过程的一部分?

android - Retrofit 2 使用 POST 发送对象

java - ArrayList<Object> 发送槽套接字

android - list 中 Activity 样式更改时的选项菜单样式更改

c# - 为什么 'Any CPU (prefer 32-bit)' 允许我在 .NET 4.5 下分配比 x86 更多的内存?

c++ - OpenCV 尝试分配 10 艾字节

Java OutOfMemoryError 奇怪的行为

android - 使用 Universal Image Loader 在 vi​​ewpager 上启用缩放?