离开活动去另一个活动时,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 是否正在清理,请将以下代码添加到您的应用程序条目 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 中使用 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 没有被调用的主要内容,如果未能解决你的问题,请参考以下文章
Android 谷歌云视觉 API 获取 Json 并使用 Json 去另一个活动