我正在运行一个正在处理的应用程序中的OutOfMemoryErrors,我很难弄清楚如何解决这个问题以及究竟是什么问题。我使用FragmentStatePagerAdapter,因为这看起来是最好的/推荐的选择。我也使用Universal Image Loader v.1.8.4。会发生什么情况是,当您浏览视图时,堆会增长并最终耗尽内存。这里有一个小样本输出:FragmentStatePagerAdapter OutOfMemoryError
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
首先,是的,我已经做了很多挖计算器和其他网站试图找出是什么问题的。我试过各种解决方案,回收位图,使用unbindDrawables,并尝试删除浏览器的消息/回收位图(...)。这些都没有为我工作(我可以提供更多的细节,如果我需要做什么)。
因此,简而言之,我可以使用修改后的版本this example(来自Google Developers网站)重现我的问题。我修改了一下,与Universal Image Loader v.1.8.4一起工作,也使布局更复杂一点,以模仿我在我正在工作的应用程序中所拥有的内容。我改变布局的原因是因为如果你的布局非常简单并且只包含一个图像和一些文本字段,那么所有东西都可以正常工作。当布局变得更加复杂时,并且当您开始向适配器添加更多页面时,您将开始遇到OOM错误。然而,我不确定这是布局还是UIL的问题...继续阅读...
我在Eclipse中运行MAT,以下是唯一的泄漏可疑报告(仅有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
如果你再检查出的支配树,扩大ScreenSlidePagerAdapter,它表明59的25项以下:
> java.util.ArrayList @ 0x4216ccf0
> java.lang.Object[60] @ 0x44b07d8
> android.app.Fragment$SavedState @ 0x439bd038
我用这个工具没有专家,我m对于Android和一般的开发来说都很新颖,但看起来适配器的保存状态不是正确清除,这就是导致OOM问题的原因(它保存了整个视图,而不仅仅是位图)。但是,我一直无法弄清楚如何清除/释放/销毁/保存的任何状态数据,或者我在其他地方做错了什么。我遇到了一篇文章,说要尝试使用.setSaveEnabled(false)
,但这没有什么区别,我仍然遇到了OOM错误。我甚至尝试覆盖适配器的saveState(),并返回null,这也没有任何区别。
下面是相关的代码/配置信息是应该有希望回答了大部分问题:
对于UIL,我只使用默认的配置,因为变化似乎并没有有所作为:
imageLoader.init(ImageLoaderConfiguration.createDefault(this));
ScreenSlideActivity:
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,通过上述活性称为:
对于ViewPager使用ScreenSlideActivity和idpublic 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;
}
}
布局activity_screen_slide.xml:
<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" />
fragment_screen_slide_page。通过ScreenSlidePageFragment使用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错误的?
终于!,一直在寻找类似的解决方案。干杯 – 2014-09-24 07:50:31
为什么unbindDrawables()方法在我的情况下给了空指针异常? – 2014-11-04 12:09:00
@SalmanKhan,这可能是因为你传递给它一个空视图。确保所有视图/变量都已正确设置。没有代码示例,没有人能真正帮助你。在这种情况下,最好将您的代码作为问题发布以获得帮助。 – Jason 2014-11-06 05:31:05