当离开活动去另一个Activity时,Xamarin Android Finalizer没有被调用

时间:2015-03-04 19:22:44

标签: c# android xamarin finalizer

离开活动后永远不会调用终结器。这是否意味着即使我继续进行下一个活动,活动仍然存在。

namespace XamarinTest {
[Activity(Label = "XamarinTest", Icon = "@drawable/icon")]
public class MainActivity : Activity {
    private int count = 1;

    private TextView density;

    protected override void OnCreate(Bundle bundle) {
        base.OnCreate(bundle);
        // Set our view from the "main" layout resource
        SetContentView(Resource.Layout.ScreenData);
        density = FindViewById<TextView>(Resource.Id.Density);

        var pendingInent = new Intent();
        pendingInent.SetFlags(ActivityFlags.ClearTop);
        pendingInent.SetClass(this, typeof(TestActivity));
        StartActivity(pendingInent);
        Finish();
    }


    ~MainActivity() {

        Console.WriteLine("Finalizer called");
    }

  protected override void Dispose(bool disposing){
        if (disposing) {
            density.Dispose();
            density = null;
        }
        base.Dispose(disposing);
    }

  }
}

1 个答案:

答案 0 :(得分:28)

这实际上非常复杂;关于活动仍在存在的简短回答是肯定的,不是。如果您已正确清理了Activity的资源,您的活动将被垃圾收集器清理(最终)。

关于清理,要知道Xamarin discourages (slide 44 onwards)使用终结器进行清理。这就是原因:

  
      
  • 不保证在任何截止日期内运行。
  •   
  • 他们不按特定顺序跑。
  •   
  • 他们让对象活得更久。
  •   
  • GC不了解非托管资源。
  •   

因此,使用终结器执行清理是错误的处理方式...如果要确保销毁MainActivity,请手动处理Activity OnDestroy { {1}}回调:

protected override void OnDestroy ()
{
    base.OnDestroy ();
    this.Dispose (); // Sever java binding.
}

这将导致Mono在下一个垃圾收集周期(GC.Collect(GC.MaxGeneration))中破坏peer object连接并销毁活动。来自文档:

  

要缩短对象的生命周期,应调用Java.Lang.Object.Dispose()。这将手动&#34;切断&#34;通过释放全局引用来连接两个VM之间的对象,从而允许更快地收集对象。

请注意那里的通话顺序,{/ 1}} 必须在任何调用回Android版本的代码后调用。为什么? Java和.NET之间的所有连接现在都被破坏,以允许Android回收资源,因此任何使用Android-land对象(Fragment,Activity,Adapter)的代码都将失败。

现在,介绍一些Activity泄漏的调试技巧。要验证您的活动是否正在清理,请将以下代码添加到您的应用条目this.Dispose()的{​​{1}}方法中:

OnCreate

这使StrictMode成为一种有用的调试工具,可以在您泄露资源时愉快地通知您。如果您的某个应用活动未正确发布,它会将类似内容转储到输出流:

Activity

将此与var vmPolicy = new StrictMode.VmPolicy.Builder (); StrictMode.SetVmPolicy (vmPolicy.DetectActivityLeaks().PenaltyLog().Build ()); 调用相结合,您可以检查是否正在发布活动。以下是您在Xamarin.Android中通常[StrictMode] class activitydispose.LeakyActivity; instances=2; limit=1 [StrictMode] android.os.StrictMode$InstanceCountViolation: class activitydispose.LeakyActivity; instances=2; limit=1 [StrictMode] at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1) 及其资源的方式:

Dispose()