2

我试图结合 mvvmcross-framework 创建嵌套的 recyclerview,它实际上很容易工作,但现在我遇到了内存不足的异常。

设想

我有一个大约 3000 个条目的列表,这些条目的名称复杂而长,分为 8 个类别。用户可以通过复选框选择条目,以便稍后将它们分配给任务。

即使听起来条目太多,但如果用户有一些背景知识,实际上很容易浏览它们,所以我宁愿在这一点上不改变它。

代码

首先是类别和条目(通道)的简化数据模型:

    public class ChannelCategory 
{
    public ChannelCategory(String sName)
    {
        Name = sName;
        Channels = new List<Channel>();
    }

    public string Name { get; set; }
    public List<Channel> Channels { get; set; }
}

    public class Channel
{
    public string Name { get; protected set; 
    public bool Selected { get; set; }

    public Channel(String sName)
    {
        Name = sName;
        Selected = false;
    }
}

然后是刚刚被 MVVMCross 映射的 axml 文件:

片段通道.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-auto"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <SearchView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text=""
        android:iconifiedByDefault="false"
        local:MvxBind="Query SearchString" />
    <MvxRecyclerView
        android:id="@+id/lvChannelList"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scrollbars="vertical"
        android:cacheColorHint="#00000000"
        android:choiceMode="singleChoice"
        local:MvxItemTemplate="@layout/listitem_channelcategory"
        local:MvxBind="ItemsSource Categories" />
</LinearLayout>

listitem_channelcategory.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-auto"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/roundborder">
    <CheckBox
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:layout_gravity="center_horizontal"
        android:layout_marginRight="5dp"
        android:padding="10dp"
        android:textColor="@color/black"
        android:textStyle="bold"
        local:MvxBind="Text (Name+Channels.Count)" />
  <MvxRecyclerView
      android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:scrollbars="vertical"
        android:cacheColorHint="#00000000"
        android:choiceMode="singleChoice"
        local:MvxItemTemplate="@layout/listitem_channel"
        local:MvxBind="ItemsSource Channels" />
</LinearLayout>

listitem_channel.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-auto"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/roundborder">
    <CheckBox
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:layout_gravity="center_horizontal"
        android:layout_marginRight="5dp"
        android:padding="10dp"
        android:textColor="@color/black"
        local:MvxBind="Text Name; Checked Selected" />
</LinearLayout>

问题

所以基本上我有一个ViewModel,它被分配给一个视图(fragment_channels)显示一个类别列表(listitem_categories),其中每个类别显示一个频道列表(listitem_channels)。一切都由 MVVMCross-Framework 处理。它工作正常,直到我向下滚动到另一个类别,然后它只是冻结了一段时间,几次后它因内存不足异常而崩溃。Atm 我可以通过给内部 recyclerviews 一个固定大小来延迟它。

有谁知道我可以改变什么或者我做错了什么?也许我不应该只是一个嵌套的recyclerview,但到这一点的处理真的很容易和直观。

MVVMCross Android 支持版本和 Co 是 4.1.5,Xamarin Android 支持库是 23.3.0

堆栈跟踪

04-22 12:17:23.207 I/MonoDroid( 7556): UNHANDLED EXCEPTION:
04-22 12:17:23.217 I/MonoDroid( 7556): Java.Lang.OutOfMemoryError: Failed to allocate a 36876 byte allocation with 14092 free bytes and 13KB until OOM
04-22 12:17:23.227 I/MonoDroid( 7556):   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/3053/a94a03b5/source/mono/external/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143 
04-22 12:17:23.227 I/MonoDroid( 7556):   at Android.Runtime.JNIEnv.CallObjectMethod (IntPtr jobject, IntPtr jmethod, Android.Runtime.JValue* parms) [0x00064] in /Users/builder/data/lanes/3053/a94a03b5/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:195 
04-22 12:17:23.227 I/MonoDroid( 7556):   at Android.Views.LayoutInflater+IFactory2Invoker.OnCreateView (Android.Views.View parent, System.String name, Android.Content.Context context, IAttributeSet attrs) [0x0008c] in /Users/builder/data/lanes/3053/a94a03b5/source/monodroid/src/Mono.Android/platforms/android-23/src/generated/Android.Views.LayoutInflater.cs:185 
04-22 12:17:23.227 I/MonoDroid( 7556):   at MvvmCross.Binding.Droid.Views.MvxLayoutInflater+DelegateFactory2.OnCreateView (Android.Views.View parent, System.String name, Android.Content.Context context, IAttributeSet attrs) [0x00020] in <filename unknown>:0 
04-22 12:17:23.227 I/MonoDroid( 7556):   at MvvmCross.Binding.Droid.Binders.MvxLayoutInflaterCompat+FactoryWrapper2.OnCreateView (Android.Views.View parent, System.String name, Android.Content.Context context, IAttributeSet attrs) [0x00000] in <filename unknown>:0 
04-22 12:17:23.227 I/MonoDroid( 7556):   at Android.Views.LayoutInflater+IFactory2Invoker.n_OnCreateView_Landroid_view_View_Ljava_lang_String_Landroid_content_Context_Landroid_util_AttributeSet_ (IntPtr jnienv, IntPtr native__this, IntPtr native_parent, IntPtr native_name, IntPtr native_context, IntPtr native_attrs) [0x0002c] in /Users/builder/data/lanes/3053/a94a03b5/source/monodroid/src/Mono.Android/platforms/android-23/src/generated/Android.Views.LayoutInflater.cs:169 
04-22 12:17:23.227 I/MonoDroid( 7556):   at (wrapper dynamic-method) System.Object:bafdfe11-a146-4499-92d6-ece4428264a4 (intptr,intptr,intptr,intptr,intptr,intptr)
04-22 12:17:23.237 I/MonoDroid( 7556):   --- End of managed exception stack trace ---
04-22 12:17:23.237 I/MonoDroid( 7556): java.lang.OutOfMemoryError: Failed to allocate a 36876 byte allocation with 14092 free bytes and 13KB until OOM
04-22 12:17:23.237 I/MonoDroid( 7556):  at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
04-22 12:17:23.237 I/MonoDroid( 7556):  at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
04-22 12:17:23.237 I/MonoDroid( 7556):  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:726)
04-22 12:17:23.237 I/MonoDroid( 7556):  at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:547)
04-22 12:17:23.237 I/MonoDroid( 7556):  at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:575)
04-22 12:17:23.237 I/MonoDroid( 7556):  at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:605)
04-22 12:17:23.237 I/MonoDroid( 7556):  at android.graphics.drawable.BitmapDrawable.updateStateFromTypedArray(BitmapDrawable.java:759)
04-22 12:17:23.237 I/MonoDroid( 7556):  at android.graphics.drawable.BitmapDrawable.inflate(BitmapDrawable.java:726)
04-22 12:17:23.237 I/MonoDroid( 7556):  at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:1150)
04-22 12:17:23.237 I/MonoDroid( 7556):  at android.graphics.drawable.AnimatedStateListDrawable.parseItem(AnimatedStateListDrawable.java:493)
04-22 12:17:23.237 I/MonoDroid( 7556):  at android.graphics.drawable.AnimatedStateListDrawable.inflate(AnimatedStateListDrawable.java:396)
04-22 12:17:23.237 I/MonoDroid( 7556):  at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:1150)
04-22 12:17:23.237 I/MonoDroid( 7556):  at android.graphics.drawable.Drawable.createFromXml(Drawable.java:1063)
04-22 12:17:23.237 I/MonoDroid( 7556):  at android.content.res.Resources.loadDrawableForCookie(Resources.java:3719)
04-22 12:17:23.247 I/MonoDroid( 7556):  at android.content.res.Resources.loadDrawable(Resources.java:3603)
04-22 12:17:23.247 I/MonoDroid( 7556):  at android.content.res.TypedArray.getDrawable(TypedArray.java:762)
04-22 12:17:23.247 I/MonoDroid( 7556):  at android.widget.CompoundButton.<init>(CompoundButton.java:89)
04-22 12:17:23.247 I/MonoDroid( 7556):  at android.widget.CheckBox.<init>(CheckBox.java:72)
04-22 12:17:23.247 I/MonoDroid( 7556):  at android.widget.CheckBox.<init>(CheckBox.java:68)
04-22 12:17:23.247 I/MonoDroid( 7556):  at android.support.v7.widget.AppCompatCheckBox.<init>(AppCompatCheckBox.java:58)
04-22 12:17:23.247 I/MonoDroid( 7556):  at android.support.v7.widget.AppCompatCheckBox.<init>(AppCompatCheckBox.java:54)
04-22 12:17:23.247 I/MonoDroid( 7556):  at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:117)
04-22 12:17:23.247 I/MonoDroid( 7556):  at android.support.v7.app.AppCompatDelegateImplV7.createView(AppCompatDelegateImplV7.java:972)
04-22 12:17:23.247 I/MonoDroid( 7556):  at android.support.v7.app.AppCompatDelegateImplV7.onCreateView(AppCompatDelegateImplV7.java:1030)
04-22 12:17:23.257 I/MonoDroid( 7556):  at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44)
04-22 12:17:23.257 I/MonoDroid( 7556):  at md59292f1b7dcad9ff99bb047144087b6e8.MvxLayoutInflaterCompat_FactoryWrapper2.n_onCreateView(Native Method)
04-22 12:17:23.257 I/MonoDroid( 7556):  at md59292f1b7dcad9ff99bb047144087b6e8.MvxLayoutInflaterCompat_FactoryWrapper2.onCreateView(MvxLayoutInflaterCompat_FactoryWrapper2.java:31)
04-22 12:17:23.257 I/MonoDroid( 7556):  at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:181)
04-22 12:17:23.257 I/MonoDroid( 7556):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:732)
04-22 12:17:23.257 I/MonoDroid( 7556):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
04-22 12:17:23.257 I/MonoDroid( 7556):  at android.view.LayoutInflater.inflate(LayoutInflater.java:511)
04-22 12:17:23.267 I/MonoDroid( 7556):  at android.view.LayoutInflater.inflate(LayoutInflater.java:415)
04-22 12:17:23.267 I/MonoDroid( 7556):  at md53ffd798107a36773482afea9a9f07756.MvxRecyclerAdapter.n_onCreateViewHolder(Native Method)
04-22 12:17:23.267 I/MonoDroid( 7556):  at md53ffd798107a36773482afea9a9f07756.MvxRecyclerAdapter.onCreateViewHolder(MvxRecyclerAdapter.java:49)
04-22 12:17:23.267 I/MonoDroid( 7556):  at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:5482)
04-22 12:17:23.267 I/MonoDroid( 7556):  at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4707)
04-22 12:17:23.267 I/MonoDroid( 7556):  at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4617)
04-22 12:17:23.267 I/MonoDroid( 7556):  at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1994)
04-22 12:17:23.267 I/MonoDroid( 7556):  at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1390)
04-22 12:17:23.267 I/MonoDroid( 7556):  at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1353)
04-22 12:17:23.267 I/MonoDroid( 7556):  at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:574)
04-22 12:17:23.267 I/MonoDroid( 7556):  at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3028)
04-22 12:17:23.277 I/MonoDroid( 7556):  at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:2625)
04-22 12:17:23.277 I/MonoDroid( 7556):  at android.view.View.measure(View.java:18596)
04-22 12:17:23.277 I/MonoDroid( 7556):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5827)
04-22 12:17:23.277 I/MonoDroid( 7556):  at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1435)
04-22 12:17:23.277 I/MonoDroid( 7556):  at android.widget.LinearLayout.measureVertical(LinearLayout.java:721)
04-22 12:17:23.277 I/MonoDroid( 7556):  at android.widget.LinearLayout.onMeasure(LinearLayout.java:612)
04-22 12:17:23.277 I/MonoDroid( 7556):  at android.view.View.measure(View.java:18596)
04-22 12:17:23.277 I/MonoDroid( 7556):  at android.support.v7.widget.RecyclerView$LayoutManager.measureChildWithMargins(RecyclerView.java:7487)
04-22 12:17:23.277 I/MonoDroid( 7556):  at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1416)
04-22 12:17:23.277 I/MonoDroid( 7556):  at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1353)
04-22 12:17:23.277 I/MonoDroid( 7556):  at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1180)
04-22 12:17:23.277 I/MonoDroid( 7556):  at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1031)
04-22 12:17:23.277 I/MonoDroid( 7556):  at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:4061)
04-22 12:17:23.277 I/MonoDroid( 7556):  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:777)
04-22 12:17:23.277 I/MonoDroid( 7556):  at android.view.Choreographer.doCallbacks(Choreographer.java:590)
04-22 12:17:23.287 I/MonoDroid( 7556):  at android.view.Choreographer.doFrame(Choreographer.java:559)
04-22 12:17:23.287 I/MonoDroid( 7556):  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:763)
04-22 12:17:23.287 I/MonoDroid( 7556):  at android.os.Handler.handleCallback(Handler.java:739)
04-22 12:17:23.287 I/MonoDroid( 7556):  at android.os.Handler.dispatchMessage(Handler.java:95)
04-22 12:17:23.287 I/MonoDroid( 7556):  at android.os.Looper.loop(Looper.java:145)
04-22 12:17:23.287 I/MonoDroid( 7556):  at android.app.ActivityThread.main(ActivityThread.java:5944)
04-22 12:17:23.287 I/MonoDroid( 7556):  at java.lang.reflect.Method.invoke(Native Method)
04-22 12:17:23.287 I/MonoDroid( 7556):  at java.lang.reflect.Method.invoke(Method.java:372)
04-22 12:17:23.287 I/MonoDroid( 7556):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1389)
04-22 12:17:23.287 I/MonoDroid( 7556):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1184)

跟踪视图

跟踪视图

它似乎与 没有联系WRAP_CONTENT,只是看起来要快得多。所以可能是 RecyclerView 本身或 MVVMCross 的问题,但我真的不确定 atm。稍后将尝试隔离问题。

它似乎与 RecyclerView 没有直接关系,因为它也发生在 ListView 上,尽管我不知道这两个有多少相关,因为我是 Android 的新手。所以我猜这要么是 Android/Monodroid 问题,要么是 MVVMCross。

4

2 回答 2

0

我使用了最近由“thefex”添加到 MVVMCross 的解决方案“MvxItemTemplateSelector”,尽管这有点意味着我必须手动将我的数据结构展平(类别和通道到一层)。

https://github.com/MvvmCross/MvvmCross-AndroidSupport/pull/200

感谢这个功能!只是希望另一种方式也能奏效,但也许当我有更多空闲时间时,我可以尝试解决它。

问候西里亚克

于 2016-04-25T14:23:30.593 回答
0

问题是嵌套ListView或RecyclerView时,无法测量嵌套View的高度。

因此,它将尝试在嵌套的 RecyclerView 中布局每个视图。这意味着,如果该嵌套项有很多项,那么您的应用程序将遇到严重问题。

你真的应该避免嵌套这种类型的视图,除非你提供更多信息让 Android 系统知道如何测量孩子。

于 2016-05-01T14:07:42.473 回答