【问题标题】:Xamarin memory reclaim issuesXamarin 内存回收问题
【发布时间】:2014-03-27 13:05:23
【问题描述】:

我使用 Xamarin 有一段时间了,遇到了一个很奇怪的问题。

我可以让一个非常简单的两屏应用程序崩溃。在第一个屏幕上,我有一个 UIButtonTouchUpInside 事件。第二个,我有一个带有附加图像的UIImageView(来自本地文件)。

我所要做的就是一直在这两个视图控制器之间来回移动。

当我连接 XCode 的 Instruments 和 Activity Monitor 时,我注意到我的简单应用程序在内存被回收之前达到了 ~100MB 的内存,然后它的使用量下降到 ~15MB。

但是当我循环导航足够长的时间时,内存会达到 140MB 以上,并且应用程序会崩溃。我在开发更复杂的应用程序时发现了这种行为。当然,我正在采取所有可用的预防措施:

  • 取消订阅 ViewWillDisappear 上的事件
  • 将代表归零等。

基本上,在我的复杂应用程序中,我已经为所有UIViewControllers 覆盖了我的基类中的Dispose 方法,我可以看到Dispose 方法在每个视图控制器上都使用disposing == false 调用显示。但是,内存使用量并没有下降。

这有什么问题?

我想指出几点:

  • 我的 Xamarin Studio 是最新的,
  • 当我在 iPhone 3GS iOS 6.1.3 上以调试模式测试应用程序时出现崩溃
  • 在简单的应用程序中,图像是 1024x1024 JPG 文件。

这里有一些代码示例:

public partial class SimpleTestViewController : UIViewController 
{
    private UIButton button;
    public SimpleTestViewController () : base ("SimpleTestViewController", null) { }

    public override void DidReceiveMemoryWarning ()
    {
        // Releases the view if it doesn't have a superview.
        base.DidReceiveMemoryWarning ();

        // Release any cached data, images, etc that aren't in use.
    }

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
        button = new UIButton (new RectangleF(0, 100, 100, 50));
        button.BackgroundColor = UIColor.Red;
        button.TouchUpInside += (sender, e) => {
            this.NavigationController.PushViewController(new SecondView(), true);
        };
        this.Add (button);

        // Perform any additional setup after loading the view, typically from a nib.
    }
}

public partial class SecondView : UIViewController
{
    private UIImageView _imageView;

    public SecondView () : base ("SecondView", null) { }

    public override void DidReceiveMemoryWarning ()
    {
        // Releases the view if it doesn't have a superview.
        base.DidReceiveMemoryWarning ();

        // Release any cached data, images, etc that aren't in use.
    }

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();

        _imageView = new UIImageView (new RectangleF(0,0, 200, 200));
        _imageView.Image = UIImage.FromFile ("Images/image.jpg");
        this.Add (_imageView);
        // Perform any additional setup after loading the view, typically from a nib.
    }

    protected override void Dispose (bool disposing)
    {
        System.Diagnostics.Debug.WriteLine("Disposing " +this.GetType() 
            + " hash code " + this.GetHashCode() 
            + " disposing flag "+disposing);
        base.Dispose (disposing);
    }
}

【问题讨论】:

    标签: c# memory xamarin memory-management xamarin.ios


    【解决方案1】:

    您正在创建按钮/图像的实例并将它们存储在支持字段中,并且您没有在控制器的Dispose 中对它们调用Dispose。控制器实例化了它们,所以你必须清除它们。

    在上面的示例中,您也没有取消按钮 TouchUpInside 事件。我建议不要为此使用 lambda,实际上为它创建一个方法,以便以后更容易分离。

    TouchUpInside -= this.Method; 
    

    此外,您不会将图像从添加到的视图中删除。

    我知道你说你在视图中做这些事情,它会消失,但这在你的示例代码中没有发生。你能提供一个完整的例子吗?

    【讨论】:

    • +1 事实上,必须处置所有一次性物品以释放资源,尤其是在移动设备等受限设备中。
    • 好的,但是我 c# 的 dispose 模式看起来像这样: public override Dispose(bool disposing) { if(disposing) { _itemToDispose.Dispose();当对象被终结时,被覆盖的方法 Dispose 将调用 dispose 等于 false,不是吗?所以不会在 _itemToDispose 上调用 Dispose。
    • 这就是为什么你必须在 if 块之外将 _itemToDipose 设置为 null 作为额外的预防措施
    猜你喜欢
    • 2018-12-07
    • 2015-04-15
    • 2016-10-24
    • 1970-01-01
    • 1970-01-01
    • 2018-01-21
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    相关资源
    最近更新 更多