Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android删除的视图不会被垃圾收集_Android_Xamarin.android - Fatal编程技术网

Android删除的视图不会被垃圾收集

Android删除的视图不会被垃圾收集,android,xamarin.android,Android,Xamarin.android,我正在与内存问题作斗争,所以我设计了一个小的测试应用程序,试图了解虚拟机如何处理垃圾收集。 下面的代码非常简单 该活动仅由一个线性布局组成 每隔一秒钟,计时器就会调用一个方法,该方法1)从LinearLayout中删除所有子项2)将3000个新文本视图添加到布局中 使用DDMS,我可以看到实例化的对象数量不断增加,并且从LinearLayout中删除的子对象永远不会被收集。 为什么呢 namespace MemoryTests { [Activity(Label = "MemoryTes

我正在与内存问题作斗争,所以我设计了一个小的测试应用程序,试图了解虚拟机如何处理垃圾收集。 下面的代码非常简单

  • 该活动仅由一个线性布局组成
  • 每隔一秒钟,计时器就会调用一个方法,该方法1)从LinearLayout中删除所有子项2)将3000个新文本视图添加到布局中
  • 使用DDMS,我可以看到实例化的对象数量不断增加,并且从LinearLayout中删除的子对象永远不会被收集。 为什么呢

    namespace MemoryTests
    {
        [Activity(Label = "MemoryTests", MainLauncher = true, Icon = "@drawable/icon")]
        public class Activity1 : Activity
        {
            private Timer _timer = new Timer();
    
            protected override void OnCreate(Bundle bundle)
            {
                base.OnCreate(bundle);
    
                // Set our view from the "main" layout resource
                SetContentView(Resource.Layout.Main);
                _timer.Interval = 1000;
                _timer.Elapsed += AddTextViews;
                _timer.Start();
            }
    
            public void AddTextViews(object o, EventArgs args)
            {
                RunOnUiThread(() =>
                                  {
                                      var layout = FindViewById<LinearLayout>(Resource.Id.layout);
                                      layout.RemoveAllViews();
                                      for (int i = 0; i < 3000; i++)
                                      {
                                          TextView tx = new TextView(ApplicationContext);
                                          layout.AddView(tx);
                                      }
                                  });
            }
        }
    }
    
    名称空间内存测试
    {
    [活动(Label=“MemoryTests”,MainLauncher=true,Icon=“@drawable/Icon”)]
    公共课堂活动1:活动
    {
    专用计时器_Timer=新计时器();
    创建时受保护的覆盖无效(捆绑包)
    {
    base.OnCreate(bundle);
    //从“主”布局资源设置视图
    SetContentView(Resource.Layout.Main);
    _计时器。间隔=1000;
    _timer.appeased+=AddTextViews;
    _timer.Start();
    }
    public void addTextView(对象o、事件args args)
    {
    RunOnUiThread(()=>
    {
    var layout=findviewbyd(Resource.Id.layout);
    layout.removeallview();
    对于(int i=0;i<3000;i++)
    {
    TextView tx=新的TextView(ApplicationContext);
    布局。添加视图(tx);
    }
    });
    }
    }
    }
    
    好的,因此在这种特殊情况下,代码的问题是您没有在
    布局上调用
    Invalidate()
    。这意味着,
    layout
    ,即使您在其上调用了
    RemoveAllViews()
    ,也没有重新绘制,仍然认为它包含以前的所有
    TextView
    实例


    因此,当您调用
    Invalidate()
    时,它会使用新的
    TextView
    实例重新绘制自身,并忘记关于旧实例的所有内容。现在,只要没有其他引用它们,它们就可以被垃圾收集。

    你永远不会调用
    布局
    上的
    Invalidate()
    ,试试看这是否有帮助。只要你不在其他地方引用
    TextView
    实例,它们就应该被标记为垃圾收集并最终被收集。嘿,奇奇!我看到你也潜伏在Xamarin论坛顶部的StackOverflow中。Invalidate()成功了。谢谢再一次,回答得很好。对于未来的读者:如果视图有一个带有可绘制的背景集,那么调用background.SetCallback(null)以确保它将被收集是很重要的