在滑动或旋转包含位图的GridView的视图时,我会得到随机的内存异常。
正在使用BitmapHelpers类来实例化图像(从另一个SO帖子中获取源)。
我不确定问题是什么,我还没有运行内存分析器(我在桌面上安装了ADB)。
我已经尝试注释掉RecycleBitmap()调用,并在SetImage()之后定位,但没有用。
活动
public class AttachmentsFragment : Activity
{
//...
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle)
{
//...
ImageViewGridAdapter attachmentGrid.Adapter = new ImageViewGridAdapter(Activity, Model.Attachments, _pictureWidth, _pictureHeight);
//...
}
//...
}
GridView适配器
public class ImageViewGridAdapter : ArrayAdapter<File>
{
private readonly List<File> _imageFiles;
public int PictureWidth { get; set; }
public int PictureHeight { get; set; }
public ImageViewGridAdapter(Context context, List<File> imageFiles, int w, int h) : base(context, 0, imageFiles)
{
_imageFiles = imageFiles;
PictureWidth = w;
PictureHeight = h;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
ImageView v = (ImageView) convertView;
if (v == null)
{
LayoutInflater li = (LayoutInflater) this.Context.GetSystemService(Context.LayoutInflaterService);
v = (ImageView) li.Inflate(Resource.Layout.GridItem_Image, null);
}
File imageFile = _imageFiles[position];
if (imageFile != null)
{
int width = PictureWidth;
int height = PictureHeight;
if( (new File(imageFile.Path)).Exists() )
{
using (Bitmap bitmap = imageFile.Path.LoadAndResizeBitmap(width, height))
{
v.RecycleBitmap();
v.SetImageBitmap(bitmap);
}
}
}
return v;
}
}
BitmapHelpers
public static class BitmapHelpers
{
/// <summary>
/// This method will recyle the memory help by a bitmap in an ImageView
/// </summary>
/// <param name="imageView">Image view.</param>
public static void RecycleBitmap(this ImageView imageView)
{
if (imageView == null) {
return;
}
Drawable toRecycle = imageView.Drawable;
if (toRecycle != null) {
((BitmapDrawable)toRecycle).Bitmap.Recycle ();
}
}
/// <summary>
/// Load the image from the device, and resize it to the specified dimensions.
/// </summary>
/// <returns>The and resize bitmap.</returns>
/// <param name="fileName">File name.</param>
/// <param name="width">Width.</param>
/// <param name="height">Height.</param>
public static Bitmap LoadAndResizeBitmap(this string fileName, int width, int height)
{
// First we get the the dimensions of the file on disk
BitmapFactory.Options options = new BitmapFactory.Options
{
InPurgeable = true,
InJustDecodeBounds = true
};
BitmapFactory.DecodeFile(fileName, options);
// Next we calculate the ratio that we need to resize the image by
// in order to fit the requested dimensions.
int outHeight = options.OutHeight;
int outWidth = options.OutWidth;
int inSampleSize = 1;
if (outHeight > height || outWidth > width)
{
inSampleSize = outWidth > outHeight
? outHeight / height
: outWidth / width;
}
// Now we will load the image and have BitmapFactory resize it for us.
options.InSampleSize = inSampleSize;
options.InJustDecodeBounds = false;
Bitmap resizedBitmap = BitmapFactory.DecodeFile(fileName, options);
return resizedBitmap;
}
}
布局
<?xml version="1.0" encoding="utf-8"?>
<fieldinspection.droid.views.LinearLayout2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_record_inspection"
android:tag="panel_4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#FF200000">
<TabHost
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_record_detail_tab"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#FFAA8800">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<include layout="@layout/PagedFragmentRecordNoteBox_InspectionNotes"/>
<include layout="@layout/RecordDetailsInspectionTabAttachments"/>
</FrameLayout>
</LinearLayout>
</TabHost>
</fieldinspection.droid.views.LinearLayout2>
标签布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_record_inspections_attachments_tab"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/grey_solid">
<fieldinspection.droid.views.custom.AttachmentButton
android:id="@+id/btn_record_inspections_attachments_tab_button"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_margin="10dp"
android:text="Add New Attachment"/>
<GridView
android:id="@+id/gv_record_inspections_attachments_tab_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="3"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:gravity="center"/>
</LinearLayout>
堆栈跟踪
05-09 17:06:05.240: E/dalvikvm-heap(2848): Out of memory on a 786448-byte allocation.
05-09 17:06:05.240: I/dalvikvm(2848): "main" prio=5 tid=1 RUNNABLE
05-09 17:06:05.240: I/dalvikvm(2848): | group="main" sCount=0 dsCount=0 obj=0x40a4d460 self=0xae1828
05-09 17:06:05.240: I/dalvikvm(2848): | sysTid=2848 nice=0 sched=0/0 cgrp=default handle=1074459784
05-09 17:06:05.240: I/dalvikvm(2848): | schedstat=( 133234532000 27301683000 107351 ) utm=11520 stm=1803 core=1
05-09 17:06:05.240: I/dalvikvm(2848): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
05-09 17:06:05.260: I/dalvikvm(2848): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493)
05-09 17:06:05.260: I/dalvikvm(2848): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:299)
05-09 17:06:05.260: I/dalvikvm(2848): at fieldinspection.droid.views.ImageViewGridAdapter.n_getView(Native Method)
05-09 17:06:05.260: I/dalvikvm(2848): at fieldinspection.droid.views.ImageViewGridAdapter.getView(ImageViewGridAdapter.java:68)
05-09 17:06:05.260: I/dalvikvm(2848): at android.widget.AbsListView.obtainView(AbsListView.java:2033)
05-09 17:06:05.260: I/dalvikvm(2848): at android.widget.GridView.makeAndAddView(GridView.java:1323)
05-09 17:06:05.260: I/dalvikvm(2848): at android.widget.GridView.makeRow(GridView.java:328)
05-09 17:06:05.260: I/dalvikvm(2848): at android.widget.GridView.fillDown(GridView.java:281)
05-09 17:06:05.260: I/dalvikvm(2848): at android.widget.GridView.fillFromTop(GridView.java:403)
05-09 17:06:05.260: I/dalvikvm(2848): at android.widget.GridView.layoutChildren(GridView.java:1215)
05-09 17:06:05.260: I/dalvikvm(2848): at android.widget.AbsListView.onLayout(AbsListView.java:1863)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
05-09 17:06:05.260: I/dalvikvm(2848): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
05-09 17:06:05.260: I/dalvikvm(2848): at dalvik.system.NativeStart.main(Native Method)
05-09 17:06:05.260: D/skia(2848): --- decoder->decode returned false
05-09 17:06:05.270: I/MonoDroid(2848): UNHANDLED EXCEPTION: Java.Lang.OutOfMemoryError: Exception of type 'Java.Lang.OutOfMemoryError' was thrown.
05-09 17:06:05.270: I/MonoDroid(2848): at Android.Runtime.JNIEnv.CallStaticObjectMethod (intptr,intptr,Android.Runtime.JValue[]) <0x00080>
05-09 17:06:05.270: I/MonoDroid(2848): at Android.Graphics.BitmapFactory.DecodeFile (string,Android.Graphics.BitmapFactory/Options) <0x00167>
05-09 17:06:05.270: I/MonoDroid(2848): at FieldInspection.Droid.Util.BitmapHelpers.LoadAndResizeBitmap (string,int,int) <0x00133>
05-09 17:06:05.270: I/MonoDroid(2848): at FieldInspection.Droid.Views.ImageViewGridAdapter.GetView (int,Android.Views.View,Android.Views.ViewGroup) <0x001f3>
05-09 17:06:05.270: I/MonoDroid(2848): at Android.Widget.ArrayAdapter.n_GetView_ILandroid_view_View_Landroid_view_ViewGroup_ (intptr,intptr,int,intptr,intptr) <0x00087>
05-09 17:06:05.270: I/MonoDroid(2848): at (wrapper dynamic-method) object.1e84d773-bf58-463e-9e97-53e6c7fa57aa (intptr,intptr,int,intptr,intptr) <0x0005b>
05-09 17:06:05.270: I/MonoDroid(2848): --- End of managed exception stack trace ---
05-09 17:06:05.270: I/MonoDroid(2848): java.lang.OutOfMemoryError
05-09 17:06:05.270: I/MonoDroid(2848): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
05-09 17:06:05.270: I/MonoDroid(2848): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493)
05-09 17:06:05.270: I/MonoDroid(2848): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:299)
05-09 17:06:05.270: I/MonoDroid(2848): at fieldinspection.droid.views.ImageViewGridAdapter.n_getView(Native Method)
05-09 17:06:05.270: I/MonoDroid(2848): at fieldinspection.droid.views.ImageViewGridAdapter.getView(ImageViewGridAdapter.java:68)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.AbsListView.obtainView(AbsListView.java:2033)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.GridView.makeAndAddView(GridView.java:1323)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.GridView.makeRow(GridView.java:328)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.GridView.fillDown(GridView.java:281)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.GridView.fillFromTop(GridView.java:403)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.GridView.layoutChildren(GridView.java:1215)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.AbsListView.onLayout(AbsListView.java:1863)
05-09 17:06:05.270: I/MonoDroid(2848): at android.view.View.layout(View.java:11283)
05-09 17:06:05.270: I/MonoDroid(2848): at android.view.ViewGroup.layout(ViewGroup.java:4224)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1628)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1486)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.LinearLayout.onLayout(LinearLayout.java:1399)
05-09 17:06:05.270: I/MonoDroid(2848): at android.view.View.layout(View.java:11283)
05-09 17:06:05.270: I/MonoDroid(2848): at android.view.ViewGroup.layout(ViewGroup.java:4224)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
05-09 17:06:05.270: I/MonoDroid(2848): at android.view.View.layout(View.java:11283)
05-09 17:06:05.270: I/MonoDroid(2848): at android.view.ViewGroup.layout(ViewGroup.java:4224)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1628)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1486)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.LinearLayout.onLayout(LinearLayout.java:1399)
05-09 17:06:05.270: I/MonoDroid(2848): at android.view.View.layout(View.java:11283)
05-09 17:06:05.270: I/MonoDroid(2848): at android.view.ViewGroup.layout(ViewGroup.java:4224)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
05-09 17:06:05.270: I/MonoDroid(2848): at android.view.View.layout(View.java:11283)
05-09 17:06:05.270: I/MonoDroid(2848): at android.view.ViewGroup.layout(ViewGroup.java:4224)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1628)
05-09 17:06:05.270: I/MonoDroid(2848): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1486)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
05-09 17:06:05.280: I/dalvikvm(2848): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
05-09 17:06:05.280: I/dalvikvm(2848): at dalvik.system.NativeStart.main(Native Method)
05-09 17:06:05.280: E/dalvikvm(2848): VM aborting
05-09 17:06:05.280: I/mono(2848): Stacktrace:
05-09 17:06:05.280: I/mono(2848): at Android.Runtime.JNIEnv.NewString (string) <0x0006b>
05-09 17:06:05.280: I/mono(2848): at Android.Util.Log.Info (string,string) <0x00073>
05-09 17:06:05.280: I/mono(2848): at Android.Runtime.AndroidEnvironment.UnhandledException (System.Exception) <0x00037>
05-09 17:06:05.280: I/mono(2848): at (wrapper dynamic-method) object.7587dfdd-5d38-472a-b7d4-2c05b2083bb2 (intptr,intptr,bool,int,int,int,int) <0x000cf>
05-09 17:06:05.280: I/mono(2848): at (wrapper native-to-managed) object.7587dfdd-5d38-472a-b7d4-2c05b2083bb2 (intptr,intptr,int,int,int,int,int) <0xffffffff>
05-09 17:06:05.280: E/mono(2848): Unhandled Exception:
05-09 17:06:05.280: E/mono(2848): System.NullReferenceException: Object reference not set to an instance of an object
05-09 17:06:05.280: E/mono(2848): at Android.Runtime.JNIEnv.NewString (string) <0x0006b>
05-09 17:06:05.280: E/mono(2848): at Android.Util.Log.Info (string,string) <0x00073>
05-09 17:06:05.280: E/mono(2848): at Android.Runtime.AndroidEnvironment.UnhandledException (System.Exception) <0x00037>
05-09 17:06:05.280: E/mono(2848): at (wrapper dynamic-method) object.7587dfdd-5d38-472a-b7d4-2c05b2083bb2 (intptr,intptr,bool,int,int,int,int) <0x000cf>
05-09 17:06:05.280: E/mono(2848): at (wrapper native-to-managed) object.7587dfdd-5d38-472a-b7d4-2c05b2083bb2 (intptr,intptr,int,int,int,int,int) <0x0009b>
05-09 17:06:05.280: I/mono(2848): [ERROR] FATAL UNHANDLED EXCEPTION: System.NullReferenceException: Object reference not set to an instance of an object
05-09 17:06:05.280: I/mono(2848): at Android.Runtime.JNIEnv.NewString (string) <0x0006b>
05-09 17:06:05.280: I/mono(2848): at Android.Util.Log.Info (string,string) <0x00073>
05-09 17:06:05.280: I/mono(2848): at Android.Runtime.AndroidEnvironment.UnhandledException (System.Exception) <0x00037>
05-09 17:06:05.280: I/mono(2848): at (wrapper dynamic-method) object.7587dfdd-5d38-472a-b7d4-2c05b2083bb2 (intptr,intptr,bool,int,int,int,int) <0x000cf>
05-09 17:06:05.280: I/mono(2848): at (wrapper native-to-managed) object.7587dfdd-5d38-472a-b7d4-2c05b2083bb2 (intptr,intptr,int,int,int,int,int) <0x0009b>
答案 0 :(得分:0)
我认为它是b / c我每次调用GetView都会实例化一个新的位图。
我要预先实例化位图并将它们传递给适配器的构造函数(而不是文件名列表)。
if( (new File(imageFile.Path)).Exists() )
{
using (Bitmap bitmap = imageFile.Path.LoadAndResizeBitmap(width, height))
{
//...
}
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
ImageView v = (ImageView) convertView;
if (v == null)
{
LayoutInflater li = (LayoutInflater) this.Context.GetSystemService(Context.LayoutInflaterService);
v = (ImageView) li.Inflate(Resource.Layout.GridItem_Image, null);
}
File imageFile = _imageFiles[position];
if (imageFile != null)
{
int width = PictureWidth;
int height = PictureHeight;
if( (new File(imageFile.Path)).Exists() )
{
using (Bitmap bitmap = imageFile.Path.LoadAndResizeBitmap(width, height))
{
v.RecycleBitmap();
v.SetImageBitmap(bitmap);
}
}
}
return v;
}