在自定义的ListView适配器内存溢出错误[单声道Android版] [英] OutOfMemory Error in Custom ListView Adapter [Mono Android]
问题描述
您好堆栈溢出的Android用户,
Hello Stack Overflow Android Users,
请与以下问题有所帮助:
Please help with the following question:
我写的一个应用程序,列出了鱼的种类的特征。我使用一个自定义的ListView适配器类(我们称之为FishSpeciesListAdapter)适配器。我有记录为节目为现在(你将最终能够添加一些自己以及)默认的27种鱼类。问题是,当我适配器连接到实际的ListView XML对象和向下滚动列表,一段时间后,我收到以下错误:
I'm writing an a feature for an app that lists species of fish. I'm using a custom ListView Adapter class (let's call this FishSpeciesListAdapter) for the adapter. I have 27 fish species recorded as a default for the program as for now (you will eventually be able to add some yourself as well). The problem is that when I link the adapter to the actual listview xml object and scroll down the list, after a while, I get the following error:
UNHANDLED EXCEPTION: Java.Lang.OutOfMemoryError: Exception of type 'Java.Lang.OutOfMemoryError' was thrown.
at Android.Runtime.JNIEnv.CallStaticObjectMethod (intptr,intptr,Android.Runtime.JValue[]) <0x00080>
at Android.Graphics.BitmapFactory.DecodeByteArray (byte[],int,int) <0x001db>
at FishinTales.FishSpeciesListAdapter.GetView (int,Android.Views.View,Android.Views.ViewGroup) <0x002f7>
at Android.Widget.BaseAdapter.n_GetView_ILandroid_view_View_Landroid_view_ViewGroup_ (intptr,intptr,int,intptr,intptr) <0x00093>
at (wrapper dynamic-method) object.5dcc133f-a229-41c4-80e2-f5f5260ecdad (intptr,intptr,int,intptr,intptr) <0x0004b>
--- End of managed exception stack trace ---
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.BitmapFactory.nativeDecodeByteArray(Native Method)
at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:392)
at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:405)
at fishintales.FishSpeciesListAdapter.n_getView(Native Method)
at fishintales.FishSpeciesListAdapter.getView(FishSpeciesListAdapter.java:55)
at android.widget.AbsListView.obtainView(AbsListView.java:1294)
at android.widget.ListView.addViewBelow(ListView.java:2896)
at android.widget.ListView.scrollListItemsBy(ListView.java:2825)
at android.widget.ListView.arrowScrollImpl(ListView.java:2322)
at android.widget.ListView.arrowScroll(ListView.java:2269)
at android.widget.ListView.commonKey(ListView.java:2071)
at android.widget.ListView.onKeyDown(ListView.java:2018)
at android.view.KeyEvent.dispatch(KeyEvent.java:1037)
at android.view.View.dispatchKeyEvent(View.java:3740)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:786)
at android.widget.ListView.dispatchKeyEvent(ListView.java:2003)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:788)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:788)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:788)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:788)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1667)
at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1102)
at android.app.Activity.dispatchKeyEvent(Activity.java:2063)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1643)
at android.view.ViewRoot.deliverKeyEventToViewHierarchy(ViewRoot.java:2471)
at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2441)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1735)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
Unhandled Exception:
Java.Lang.OutOfMemoryError: Exception of type 'Java.Lang.OutOfMemoryError' was thrown.
at Android.Runtime.JNIEnv.CallStaticObjectMethod (intptr,intptr,Android.Runtime.JValue[]) <0x00080>
at Android.Graphics.BitmapFactory.DecodeByteArray (byte[],int,int) <0x001db>
at FishinTales.FishSpeciesListAdapter.GetView (int,Android.Views.View,Android.Views.ViewGroup) <0x002f7>
at Android.Widget.BaseAdapter.n_GetView_ILandroid_view_View_Landroid_view_ViewGroup_ (intptr,intptr,int,intptr,intptr) <0x00093>
at (wrapper dynamic-method) object.5dcc133f-a229-41c4-80e2-f5f5260ecdad (intptr,intptr,int,intptr,intptr) <0x0004b>
--- End of managed exception stack trace ---
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.BitmapFactory.nativeDecodeByteArray(Native Method)
at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:392)
at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:405)
at fishintales.FishSpeciesListAdapter.n_getView(Native Met
下面是我的自定义ListAdapter:
Here's my Custom ListAdapter:
public class FishSpeciesListAdapter : BaseAdapter
{
Context n_context;
List<AppCode.Specie> n_specieData;
public FishSpeciesListAdapter (Context context, List<AppCode.Specie> specieData)
{
this.n_context = context;
this.n_specieData = specieData;
}
public override int Count {
get { return this.n_specieData.Count; }
}
public override Java.Lang.Object GetItem (int position)
{
return null;
}
public override long GetItemId (int position)
{
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public override View GetView (int position, View convertView, ViewGroup parent)
{
View v;
if(convertView==null){
LayoutInflater li = LayoutInflater.FromContext(parent.Context);
v = li.Inflate(Resource.Layout.Adapter_FishSpeciesIcon, null);
}
else
{
v = convertView;
}
ImageView iconImage = (ImageView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesIconImage);
TextView nameText = (TextView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesNameText);
TextView scientificNameText = (TextView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesScientificNameText);
nameText.Text = this.n_specieData[position].Name;
scientificNameText.Text = this.n_specieData[position].ScientificName;
if (this.n_specieData[position].RelatedMedia.AttachedPhotos.Count < 1)
{
iconImage.SetImageResource(Resource.Drawable.Icon);
}
else
{
iconImage.SetImageBitmap(BitmapFactory.DecodeByteArray(this.n_specieData[position].RelatedMedia.AttachedPhotos[0], 0, this.n_specieData[position].RelatedMedia.AttachedPhotos[0].Length));
}
return v;
}
}
其他研究以我的名义
所有图片都是在100-300KB的范围内。
是否真的会导致这个问题?
Other Research On My Behalf
All images are in the range of 100-300KB. Will this really cause this problem?
请<一href=\"http://stackoverflow.com/questions/13684806/custom-listview-adapter-showing-incorrect-values-mono-android\">reference我的最后一个帖子额外的code,因为它是一种相关的,但需要一个新的问题。感谢您的时间和帮助。
Please reference my last post for additional code as it is kind of related but needs a new question. Thanks for your time and help.
推荐答案
解决它!
这是什么做的是越来越举起的解码字节数组成位图,每次GetView已被调用。所以我所做的就是将它们转换都在构造函数和取得的位图缓存引用时被调用的GetView方法。
What it was doing was getting held up on decoding byte arrays into Bitmaps everytime GetView was being called. So what I did was convert them all in the constructor and made a cache of Bitmaps to reference when the GetView method was called.
下面是我的自定义更新的ListView适配器的作品。
Here is my updated Custom ListView Adapter that works.
public class FishSpeciesListAdapter : BaseAdapter
{
Context n_context;
List<AppCode.Specie> n_specieData;
List<Bitmap> n_bitmapCache;
public FishSpeciesListAdapter (Context context, List<AppCode.Specie> specieData)
{
this.n_context = context;
this.n_specieData = specieData;
this.n_bitmapCache = new List<Bitmap>();
this.LoadBitmapsIntoCache();
}
private void LoadBitmapsIntoCache()
{
foreach(AppCode.Specie specie in this.n_specieData)
{
if (specie.RelatedMedia.AttachedPhotos.Count < 1)
{
this.n_bitmapCache.Add(BitmapFactory.DecodeResource(this.n_context.Resources, Resource.Drawable.Icon));
}
else
{
this.n_bitmapCache.Add(BitmapFactory.DecodeByteArray(specie.RelatedMedia.AttachedPhotos[0], 0, specie.RelatedMedia.AttachedPhotos[0].Length));
}
}
}
public override int Count {
get { return this.n_specieData.Count; }
}
public override Java.Lang.Object GetItem (int position)
{
return null;
}
public override long GetItemId (int position)
{
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public override View GetView (int position, View convertView, ViewGroup parent)
{
if(convertView==null){
LayoutInflater li = LayoutInflater.FromContext(parent.Context);
convertView = li.Inflate(Resource.Layout.Adapter_FishSpeciesIcon, null);
}
ImageView iconImage = (ImageView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesIconImage);
TextView nameText = (TextView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesNameText);
TextView scientificNameText = (TextView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesScientificNameText);
nameText.Text = this.n_specieData[position].Name;
scientificNameText.Text = this.n_specieData[position].ScientificName;
iconImage.SetImageBitmap(this.n_bitmapCache[position]);
return convertView;
}
}
调用LoadBitmapsIntoCache()在构造和保存位图到列表后。这个问题得到了解决,我可以没有任何错误的内存溢出通过所有鱼的种类滚动。感谢所有谁帮助。
After calling LoadBitmapsIntoCache() in the constructor and saving the Bitmaps to a list. The problem was resolved and I could scroll through all the fish species without any OutOfMemory Errors. Thanks to all who helped.
这篇关于在自定义的ListView适配器内存溢出错误[单声道Android版]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!