在这个应用程序中,我想有一个包含微调器的列表.当我在模拟器上测试应用程序时它看起来不错,但是当我滚动它时内存很快因为gref超过2000.我知道gref可以在真实设备上更高但我仍然认为我必须做错了.
BindableList
<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>
这是否发生是因为每次滚动时都必须重建微调器项目?因为它所绑定的列表在列表中的每个项目中都是不同的.因此,在一个列表项上,微调器列表可以是六个项目,另一个可以是3个项目,依此类推.
我还没有对你所看到的行为进行全面分析 – 如果没有完整的代码示例则很难做到.但是,特别感谢JonPryor在Xamarin forums上我相信我现在至少能够更好地理解GREF在一般情况下发生的事情 – 所以我可以回答你的“为什么”问题.
绑定列表的一般情况是GREF递增:
>每次绑定一次 – 因为绑定存储在混合C#/ Java容器对象中 – https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.Binding.Droid/MvxJavaContainer.cs
>每个ListView项目一次 – 因为它在列表中使用
>对于ListView中具有绑定属性或事件的每个View对象,一次 – 例如如果绑定到每个ListView项目中的TextView和Button,则C#将存储对这些视图的引用
在您的示例中,每个列表项本身都包含一个绑定列表 – 这将导致所需的GREF数量的倍增 – 这就是您看到报告的问题的原因.
有了这种理解,显而易见的问题可能是“我们如何解决这个问题?”
这不是一个简单的问题,但我认为有一些方法可以解决这个问题.
首先,我们可以与Xamarin讨论这个问题 – 可能是应该增加可用的GREF数量 – 因为这些对象将在Java内存中,那么在C#中引用它们也许没有坏处?
其次,我们可以考虑改变实现UI绑定的方式,以便永久引用不会存储到所有对象 – 例如,如果我们知道一次性绑定(例如,对于标签),那么我们可能会看一条路线不对此功能使用XML数据绑定.例如,我们可以使用新的View手动执行此绑定.
第三,我们可以考虑更改绑定代码本身,以便对于单向绑定(从ViewModel到View),它使用FindViewById< TView>检索Android视图.在更新时,而不是使用保留的视图引用.这会更慢,但会减少所需的GREF数量.在明确声明的“一次性”绑定的情况下,此功能可能是最可实现的.
第四,这是作为应用程序开发人员最容易访问的解决方案,您可以查看更改UI实现,以便应用程序不使用这些绑定的子列表 – 例如它可以改为使用标签 – 它只按需创建微调器(通过处理代码中的Click事件).
我相信除此之外还有其他选择……
在此分析中我问自己的一个问题是,这个问题是否是MvvmCross独有的,或者是否是一个可能在所有MonoDroid应用程序中看到的问题.
我不是百分百肯定,但我认为答案是这是一个影响所有MonoDroid应用程序的一般性问题.但是,我也认为MvvmCross在这个问题上增加了一点:
>通过持有TextViews / labels之类的引用
>通过使您更容易编写引用大量Java对象的代码.
我也不认为这完全只是一个MvvmCross或MonoDroid问题.虽然由于MonoDroid的实现而突出了这个GREF限制,但这里的根本问题实际上是尝试一次做太多 – 所以你真的可以通过对设计/实现进行流式处理来提高应用程序的性能,以便减少使用观点.虽然它可能不喜欢它,但我认为MonoDroid在这方面对我们有利 – 它指出我们的UI实现有点“胖”,我们应该考虑在我们的应用程序代码中优化它.
我会在发现更多信息后更新这个答案,但我希望上述信息已经让您对这种情况的“原因”有了很好的了解.