我试图结合 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。