2

我似乎无法弄清楚为什么我的活动总是内存不足。

当我加载我的活动时,我有一堆加载到自定义列表视图适配器中的图像。当我开始活动时,屏幕加载正常。但是当我改变方向或返回并重新启动时,活动会生成内存不足异常。

这是我的活动的样子:

崩溃的鱼类活动

这是我的活动的代码:

    [Activity(Label = "FishinTales: Fish Species")]
public class Activity_View_FishSpecies : Activity
{
    #region Components
    private Model n_model;
    private ListView n_fishSpeciesListView;
    #endregion

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        // Get Application Global Model
        this.n_model = ((MyApp) this.ApplicationContext).FishingData;

        // Set our view from the "View_FishSpecies" layout resource
        SetContentView(Resource.Layout.View_FishSpecies);

        this.n_fishSpeciesListView = FindViewById<ListView> (Resource.Id.xml_fishSpeciesListView);
        this.n_fishSpeciesListView.Adapter = new FishSpeciesListAdapter (this.ApplicationContext, this.n_model.SpecieManager.Species);
    }

    protected override void OnDestroy()
    {
        base.OnDestroy();
        this.unbindDrawables(FindViewById(Resource.Id.xml_root));
        this.n_fishSpeciesListView.Adapter = null;
        this.n_fishSpeciesListView = null;
    }

    private void unbindDrawables(View view) {
        if (view.Background != null) {
            view.Background.SetCallback(null);
        }
        if (view.GetType() == typeof(ViewGroup)) {
            for (int i = 0; i < ((ViewGroup) view).ChildCount; i++) {
                unbindDrawables(((ViewGroup) view).GetChildAt(i));
            }
            ((ViewGroup) view).RemoveAllViews();
        }
    }
}

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;
    }
}

这是我在生成 OOM 错误之前的所有进程的日志。

    Loading Defaults - Successfully Loaded Defaults
Grow heap (frag case) to 6.474MB for 314670-byte allocation
Clamp target GC heap from 32.512MB to 32.000MB
796824-byte external allocation too large for this process.
VM won't let us allocate 796824 bytes
Clamp target GC heap from 33.447MB to 32.000MB
--- decoder->decode returned false
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) <0x001bb>
at FishinTales.FishSpeciesListAdapter.LoadBitmapsIntoCache () <0x00187>
at FishinTales.FishSpeciesListAdapter..ctor (Android.Content.Context,System.Collections.Generic.List`1<FishinTales.AppCode.Specie>) <0x000a3>
at FishinTales.Activity_View_FishSpecies.OnCreate (Android.OS.Bundle) <0x0012f>
at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (intptr,intptr,intptr) <0x00057>
at (wrapper dynamic-method) object.99ebf5db-74ad-4da9-b431-612691e1f213 (intptr,intptr,intptr) <0x00033>

  --- End of managed exception stack trace ---
java.lang.OutOfMemoryError: bitmap size exceeds VM budget(Heap Size=6855KB, Allocated=3089KB, Bitmap Size=26666KB)
    at android.graphics.BitmapFactory.nativeDecodeByteArray(Native Method)
    at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:625)
    at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:638)
    at fishintales.Activity_View_FishSpecies.n_onCreate(Native Method)
    at fishintales.Activity_View_FishSpecies.onCreate(Activity_View_FishSpecies.java:29)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1093)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1780)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1837)
    at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3242)
    at android.app.ActivityThread.access$1600(ActivityThread.java:132)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1037)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:143)
    at android.app.ActivityThread.main(ActivityThread.java:4196)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:507)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    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) <0x001bb>
at FishinTales.FishSpeciesListAdapter.LoadBitmapsIntoCache () <0x00187>
at FishinTales.FishSpeciesListAdapter..ctor (Android.Content.Context,System.Collections.Generic.List`1<FishinTales.AppCode.Specie>) <0x000a3>
at FishinTales.Activity_View_FishSpecies.OnCreate (Android.OS.Bundle) <0x0012f>
at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (intptr,intptr,intptr) <0x00057>
at (wrapper dynamic-method) object.99ebf5db-74ad-4da9-b431-612691e1f213 (intptr,intptr,intptr) <0x00033>

  --- End of managed exception stack trace ---
java.lang.OutOfMemoryError: bitmap size exceeds VM budget(Heap Size=6855KB, Allocated=3089KB, Bitmap Size=26666KB)
    at android.graphics.BitmapFactory.nativeDecodeByteArray(Native Method)
    at android.gra

当我最初查看活动时,一切都很好。当我离开活动并多次返回时,它最终会因上述错误而崩溃。这使我推测该错误来自内存泄漏,其中位图未正确回收。那么有没有关于如何准确地释放这些位图的例子呢?当您的位图位于自定义 ListView 适配器类中时,很难找到有关此主题的信息。当我在设置后放置 Bitmap.recycle 时,我收到另一个错误,指出 ListView 正在尝试访问回收的项目。那么我应该如何/何时根据上面的代码进行回收。

4

1 回答 1

1

我想知道您使用的是哪个版本的 Android。如果是 Jelly Bean (Android 4.1.1) 请去掉这行代码

this.n_bitmapCache.Add(BitmapFactory.DecodeResource(this.n_context.Resources, Resource.Drawable.Icon)); 

看看你是否有内存泄漏。

在更新到 Android 4.1.1 后,我的应用程序也开始出现内存泄漏,我发现问题出在

setBackgroundResource(id);

我尝试将其更改为

setBackground(context.getResources().getDrawable(id));

但仍然出现内存泄漏。如果我们尝试从资源创建可绘制对象或位图,我想确认它是我的代码中的错误还是 Jelly Bean 中的错误导致内存泄漏。很抱歉没有回答您的问题,但我们至少可以知道错误的原因并向 Android 团队提出问题。

更新 我在这个链接中找到了解决方案

对于从资源的可绘制文件夹创建的位图,请使用 setBackgroundDrawable(null)。

于 2013-01-10T06:19:31.510 回答