我正在使用mvvmcross为android开发一个应用程序。
在此应用程序中,我希望有一个包含微调器的列表。当我在模拟器上测试应用程序时,它看起来没问题,但是当我滚动它时,它很快就会耗尽内存,因为gref超过2000。我知道gref在真正的设备上可以走得更高,但我仍然认为我一定做错了什么。
装订者

    <cirrious.mvvmcross.binding.android.views.MvxBindableListView
          android:id="@+id/propertyHolder"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:layout_below="@id/obsBtLayout"
          android:layout_above="@id/photoframe"
          local:MvxBind="
          {
            'ItemsSource':{'Path':'PPHolders'},
            'ItemClick':{'Path':'PropertyClickedCommand'}
          }"
          local:MvxItemTemplate="@layout/listitem_property"
        />

listitem_property.axml(剥离)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:local="http://schemas.android.com/apk/res/AIPApp.UI.Droid"
  android:orientation="horizontal"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:background="@drawable/ListItemSelector"
  android:descendantFocusability="beforeDescendants"
  >

  <cirrious.mvvmcross.binding.android.views.MvxBindableSpinner
    android:layout_gravity="center_horizontal"
    android:layout_width="200dip"
    android:layout_height="wrap_content"
    local:MvxDropDownItemTemplate="@layout/spinneritem_propdropdown"
    local:MvxItemTemplate="@layout/spinneritem_prop"
    local:MvxBind="
    {
      'ItemsSource':{'Path':'CodeTableValues'},
      'SelectedItem':{'Path':'ObservedCodeTable'},
      'Visibility':{'Path':'IsCodeTableValue','Converter':'Visibility'}
    }"/>

</LinearLayout>

是否因为每次滚动时都必须重新生成微调器项而发生这种情况?因为它绑定到的列表在列表中的每个项目中都不同。因此,在一个列表项上,微调器列表可以是6个项,在另一个列表项上,微调器列表可以是3个项,依此类推。

最佳答案

我还没有对你所看到的行为进行全面的分析——没有完整的代码样本是很难做到的。
不过,特别感谢jonpyror的支持,我相信我现在至少对grefs在一般情况下发生的事情有了更好的理解,所以我可以回答你的“为什么”问题。
绑定列表的一般情况是gref递增:
每一组绑定一次-因为绑定存储在一个混合的c/java容器对象中-Xamarin forums
对每个listview项使用一次-因为它在列表中使用
对于列表视图中具有绑定属性或事件的每个视图对象(例如,如果您绑定到每个列表视图项中的aTextView和aButton,则c将存储对这些视图的引用
在您的示例中,每个列表项本身都将包含一个绑定列表—这将导致所需gref的数量成倍增加—这就是您看到所报告的问题的原因。
有了这种理解,显而易见的问题可能是“我们如何解决这个问题?”
这不是一个简单的问题要回答,但我认为有几种方法可以解决这个问题。
首先,我们可以和Xamarin讨论这个问题——可能应该增加可用gref的数量——因为这些对象将在Java的内存中,那么在C中引用它们也没有什么坏处吗?
其次,我们可以考虑改变ui绑定的实现方式,这样就不会将永久引用存储到所有对象—例如,如果我们一次性知道一个绑定(例如,对于一个标签),那么我们可以考虑不使用xml数据绑定来实现此功能的路由。例如,我们可以使用一个新视图手动执行此绑定。
第三,我们可以考虑更改绑定代码本身,以便对于单向绑定(从viewmodel到view),它在更新时使用FindViewById<TView>检索android视图,而不是使用对视图的保留引用。这会比较慢,但会减少所需的gref数量。在显式声明“一次性”绑定的情况下,此功能可能最容易实现。
第四,作为一个应用程序开发人员,这可能是您最容易访问的解决方案,您可以考虑更改ui实现,以便应用程序不使用这些绑定的子列表(例如,它可以使用一个标签),该标签只按需创建微调器(通过在您的代码)。
我相信除此之外还有其他选择…
在分析过程中,我问自己的一个问题是,这个问题是mvvmcross独有的,还是所有单机器人应用程序都可能遇到的问题。
我不是百分之百确定,但我想答案是,这是一个普遍的问题,会影响到所有的单机器人应用程序。不过,我也认为mvvmcross增加了一点问题:
通过保持文本视图/标签之类的引用
通过使您更容易编写引用大量java对象的代码。
我也不认为这完全是一个mvvmcross或单机器人的问题。虽然这个gref限制由于monodroid的实现而被强调,但这里的根本问题是一次尝试做太多的事情,所以您确实可以通过在设计/实现中使用流来提高应用程序的性能,从而使其使用更少的视图。虽然它可能感觉不到,但我认为Monodroid在这里帮了我们一个忙——它指出我们的UI实现有点“胖”,我们应该在应用程序代码中优化它。
我会更新这个答案,因为我发现更多,但我希望以上信息已经给你相当好的洞察'为什么'的情况。

10-08 12:57