离开活动转到另一个活动时,Xamarin Android Finalizer 没有被调用 [英] Xamarin Android Finalizer not getting called when leaving the activity to go to another Activity

查看:28
本文介绍了离开活动转到另一个活动时,Xamarin Android Finalizer 没有被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在离开活动后永远不会调用终结器.这是否意味着即使我转移到下一个活动,该活动仍然有效.

The Finalizer is never called after leaving the activity. Does that mean the activity is still alive even though I moved on to the next 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 的资源,垃圾收集器将(最终)清理您的 Activity.

This is actually remarkably complicated; the short answer, regarding the activity still being alive, is yes and no. Providing you have cleaned up the resources for your Activity correctly, your activity will be cleaned up (eventually) by the garbage collector.

关于清理,重要的是要知道 Xamarin 不鼓励(从第 44 步开始) 使用终结器.原因如下:

Regarding cleanup, it's import to know that Xamarin discourages (slide 44 onwards) using finalizers. Here's why:

  • 不保证它们会在任何截止日期内运行.
  • 它们不按特定顺序运行.
  • 它们使物体寿命更长.
  • GC 不知道非托管资源.

因此,使用终结器进行清理是错误的做事方式...如果要确保 MainActivity 被销毁,请手动将 Activity 处理在它是 OnDestroy 回调:

Therefore, using a finalizer to perform cleanup is the wrong way of doing things... If you want to ensure that MainActivity is destroyed, manually dispose the Activity in it's OnDestroy callback:

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

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

This will cause Mono to break the peer object connection and destroy the activity during the next garbage collection cycle (GC.Collect(GC.MaxGeneration)). From the docs:

为了缩短对象生命周期,应该调用 Java.Lang.Object.Dispose().这将通过释放全局引用手动切断"两个 VM 之间对象上的连接,从而更快地收集对象.

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.

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

Note the call order there, this.Dispose() must be called after any code that invokes back into Android land. Why? All the connections between Java and .NET are now broken to allow Android to reclaim resources so any code that uses Android-land objects (Fragment, Activity, Adapter) will fail.

现在,介绍一些针对 Activity 泄漏的调试技术.要验证您的 Activity 是否已被清理,请将以下代码添加到您的应用条目 ActivityOnCreate 方法中:

Now, onto some debugging techniques for Activity leaks. To verify that your activity is being cleaned up, add the following code to the OnCreate method of your apps entry Activity:

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

这将启用 StrictMode,一个有用的调试工具,当您泄漏资源时会很高兴地通知您.当您的应用活动之一未正确发布时,它会将类似以下内容的内容转储到输出流:

This enables StrictMode, a useful debugging tool that happily informs you when you've leaked resources. When one of your apps activities isn't released correctly, it will dump something like this to the output stream:

[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 中通常使用 Activity 及其资源的方式:

Combining this with the Dispose() call, you can check that activities are being released. Here is how you'd typically an Activity and its resources in 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.
}

这篇关于离开活动转到另一个活动时,Xamarin Android Finalizer 没有被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆