使用ViewHolder模式时调用Dispose()的正确时机是什么时候?

时间:2016-11-15 21:59:20

标签: android xamarin xamarin.android dispose

我使用James Montemagno描述的ViewHolder模式

https://blog.xamarin.com/creating-highly-performant-smooth-scrolling-android-listviews/

考虑到FindViewById调用的对象,我什么时候应该调用dispose?做什么是安全和正确的。我应该在某个时刻这样做: https://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/

  

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

1 个答案:

答案 0 :(得分:1)

ListView已经很老了(Android 1.0)。它是紧密耦合的,并没有考虑到性能。需要大量的黑客来保持它的相关性。 RecyclerView填补了这一空白。

https://www.youtube.com/watch?v=LqBlYJTfLP4

至于何时应致电Dispose()RecyclerView应通过LayoutManager处理此基本功能。在ViewHolder方面,您可以遵循基本的Dispose模式:

protected override void Dispose (bool disposing)
    {
        base.Dispose (disposing);
        if(ItemView != null)
        {
            ItemView.Click -= HandleClick;
        }
        _listener = null; //Listener might just be a simple Action<int> like in this example: https://github.com/xamarin/monodroid-samples/blob/master/android5.0/RecyclerViewer/RecyclerViewer/MainActivity.cs#L111
    }

您只关心处置您设置的基础和任何事件处理程序。但是,如果您的RecyclerViewView充气时使用了一些图片,那么您需要确保正确管理这些资源,因为Android GC无法将这些项目收集为它们将被Xamarin.Android的GC引用(它们将是一个小参考,比如几个字节值)。不知何故,你必须切断两个GC之间的链接,以便它有资格收集。您可以在此处详细了解GC算法:Xamarin Android garbage collection algorithm及其原因:https://developer.xamarin.com/guides/cross-platform/deployment,_testing,_and_metrics/memory_perf_best_practices/#Use_Weak_References_to_Prevent_Immortal_Objects

要做到这一点,我们可以通过几种方式切断关系:

  1. MyObject = null;
  2. MyObject.Dispose();
  3. 无论哪种方式都应该标记这些项目符合GC的条件。如果是Drawable,您可能还需要将ImageViewDrawable设置的对象设置为null,例如SetBackgroundDrawable /等

    TLDR;使用RecyclerView,并记住妥善管理任何Bitmap/Drawable资源。