编程语言
首页 > 编程语言> > c# – Xamarin Android Finalizer在离开活动去另一个Activity时没有被调用

c# – Xamarin Android Finalizer在离开活动去另一个Activity时没有被调用

作者:互联网

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

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

  }
}

解决方法:

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

关于清理,使用终结器知道Xamarin discourages (slide 44 onwards)是重要的.原因如下:

  • They are not guaranteed to run within any deadline.
  • They don’t run in a specific sequence.
  • They make objects live longer.
  • The GC doesn’t know about unmanaged resources.

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

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

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

To shorten object lifetime, Java.Lang.Object.Dispose() should be invoked. This will manually “sever” the connection on the object between the two VMs by freeing the global reference, thus allowing the objects to be collected faster.

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

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

var vmPolicy = new StrictMode.VmPolicy.Builder ();
StrictMode.SetVmPolicy (vmPolicy.DetectActivityLeaks().PenaltyLog().Build ());

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

[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.
}

标签:finalizer,android,xamarin,c-2
来源: https://codeday.me/bug/20190926/1817886.html