C# 离开活动转到其他活动时未调用Xamarin Android终结器

C# 离开活动转到其他活动时未调用Xamarin Android终结器,c#,android,xamarin,finalizer,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 vo

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

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

  }
}
名称空间测试{
[活动(Label=“xamarinest”,Icon=“@drawable/Icon”)]
公共课活动:活动{
私有整数计数=1;
私有文本视图密度;
创建时受保护的覆盖无效(捆绑包){
base.OnCreate(bundle);
//从“主”布局资源设置视图
SetContentView(Resource.Layout.ScreenData);
密度=FindViewById(Resource.Id.density);
var pendingent=新意图();
挂起设置标志(ActivityFlags.ClearTop);
SetClass(这个,typeof(TestActivity));
起始触感(悬垂);
完成();
}
~main活动(){
Console.WriteLine(“调用终结器”);
}
受保护的覆盖无效处置(布尔处置){
如果(处置){
depose();
密度=零;
}
基地。处置(处置);
}
}
}

这实际上非常复杂;关于活动仍处于活动状态的简短回答是“是”和“否”。如果您已正确清理了
活动的资源,则垃圾收集器将(最终)清理您的活动

关于清理,知道使用终结器是很重要的。原因如下:

  • 它们不保证在任何期限内运行
  • 它们不按特定的顺序运行
  • 它们使物体寿命更长
  • GC不知道非托管资源
因此,使用终结器执行清理是错误的做法。。。如果要确保销毁
main活动
,请在其
ondestory
回调中手动处理
活动

protected override void OnDestroy ()
{
    base.OnDestroy ();
    this.Dispose (); // Sever java binding.
}
这将导致Mono在下一个垃圾收集周期(
GC.Collect(GC.MaxGeneration)
)中断连接并销毁活动。从文档中:

要缩短对象生存期,应调用Java.Lang.object.Dispose()。这将通过释放全局引用手动“断开”两个VM之间对象上的连接,从而允许更快地收集对象

注意这里的调用顺序,
this.Dispose()
必须在任何调用回Android land的代码之后调用。为什么?Java和.NET之间的所有连接现在都已断开,允许Android回收资源,因此任何使用Android陆地对象(片段、活动、适配器)的代码都将失败

现在,我们来介绍一些活动泄漏的调试技术。要验证是否正在清理您的活动,请将以下代码添加到应用程序条目的
活动
OnCreate
方法中:

var vmPolicy = new StrictMode.VmPolicy.Builder ();
StrictMode.SetVmPolicy (vmPolicy.DetectActivityLeaks().PenaltyLog().Build ());
这将启用一个有用的调试工具,当您泄漏资源时,它会很高兴地通知您。如果某个应用程序活动未正确发布,它会将类似以下内容转储到输出流:

[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()
调用,可以检查是否正在释放活动。以下是您在Xamarin.Android中创建
活动及其资源的典型方式:

protected override void Dispose (bool disposing)
{
    // TODO: Dispose logic here.
    base.Dispose (disposing);
    GC.Collect(GC.MaxGeneration); // Will force cleanup but not recommended.
}

protected override void OnDestroy ()
{
    if (density != null) { // Release Java objects (buttons, adapters etc) here
        density.Dispose ();
        density = null;
    }
    base.OnDestroy ();
    this.Dispose (); // Sever java binding.
}

“这实际上非常复杂”这个信息非常有用。StrictMode Rocks StrictMode似乎只对活动起作用,我们是否也可以对片段起作用?因为它与StrictMode类似,所以不会显示关于片段的任何泄漏信息。