Monodroid - 活动结束时的免费记忆

时间:2011-11-10 09:50:01

标签: xamarin.android

这里可以找到示例代码 https://github.com/PVoLan/TestActivityDispose

我们有两项活动。一个按钮导致第二个活动。第二个活动有30个TextView(模拟复杂的UI)和后退按钮。

向前和向后切换活动会导致GREF数量快速增长。它需要大约60次点击前进和后退溢出2k限制和崩溃应用程序。

可以在存储库中找到Android日志。从日志中可以看出,由于TextViews(1543 GREF),GREF溢出最多。另一个GREFS是:

  • 按钮(55 GREFs) - backButton,显然
  • OnClickListenerImplementor(55 GREFs) - backButton.Click listenters
  • 活动2(54 GREFs)
  • 意图(54 GREF) - 活动开始者

因此,正如我们所看到的,活动完成时不会释放活动资源(尽管调用了OnDestroy) 我怎样才能正确释放所有这些GREF?

1 个答案:

答案 0 :(得分:1)

问题是这个过程中有两个GC(Dalvik& Mono),并且都不知道对方使用了多少内存。例如,所有Mono看到的TextView个实例都是一个非常小的对象(主要是IntPtr和来自Java.Lang.Object的其他支持字段):

namespace Java.Lang {
    public class Object {
        IntPtr handle;
        // ...
    }
}
namespace Android.Widget {
    public class TextView : Java.Lang.Object {
        // ...
    }
}

也就是说,对于大多数绑定类型,没有后果的数据成员,并且C#包装器非常小。 Mono不知道 - 也不知道 - 有一个与Object.handle相关联的Java对象,以及(更重要的是)该对象引用了多少内存。

因此,您偶尔需要帮助它:

// https://github.com/PVoLan/TestActivityDispose/blob/master/Test/Activity2.cs
public class Activity2 {
    // ...
    protected override void OnDestroy ()
    {
        Android.Util.Log.Info("----------", "Destroy");
        base.OnDestroy ();
        GC.Collect ();
    }
}

添加的GC.Collect()调用将为Mono的GC提供执行和收集垃圾对象的机会。添加该行后,反复点击“Hello World,Click Me!”和“返回”等级为93-126 grefs(取决于您正在进行的活动)。