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

Posted

技术标签:

【中文标题】离开活动去另一个活动时,Xamarin Android Finalizer 没有被调用【英文标题】:Xamarin Android Finalizer not getting called when leaving the activity to go to another Activity 【发布时间】:2015-05-05 22:46:44 【问题描述】:

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

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】:

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

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

不保证它们会在任何期限内运行。 它们不按特定顺序运行。 它们使对象寿命更长。 GC 不知道非托管资源。

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

protected override void OnDestroy ()

    base.OnDestroy ();
    this.Dispose (); // Sever java binding.

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

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

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

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

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 中使用 Activity 及其资源:

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 摇滚 StrictMode 似乎只适用于活动,我们是否也可以为 Fragments 做到这一点?因为它确实像 StrictMode 一样不显示任何有关 Fragments 的泄漏信息。

以上是关于离开活动去另一个活动时,Xamarin Android Finalizer 没有被调用的主要内容,如果未能解决你的问题,请参考以下文章

java 去另一个活动

Android 谷歌云视觉 API 获取 Json 并使用 Json 去另一个活动

离开活动并返回时保持设置按钮颜色

通过 Xamarin 中的新活动加载时布局不显示内容

Xamarin.iOS 为啥在设备上调试时 HKAnchoredObjectQuery 处于非活动状态然后停用?

Xamarin.iOS 为啥在设备上调试时 HKAnchoredObjectQuery 处于非活动状态然后停用?