我已经尝试与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文件:
fragment_channels.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我可以通过给内部回收站点提供固定的大小来延迟它。
有谁知道我可以改变什么或我做错了什么?也许我不应该只是一个嵌套的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。
我使用了最近由“thefex”添加到MVVMCross的解决方案“MvxItemTemplateSelector”,尽管它有点意味着我必须手工压缩我的数据结构(类别和通道到一层)。
https://github.com/MvvmCross/MvvmCross-AndroidSupport/pull/200
谢谢你的这个功能!只是希望另一种方式也可以工作,但也许我可以尝试解决它,当我有更多的时间。
问候Cyriac
问题是,在嵌套ListView或RecyclerView时,它无法测量嵌套View的高度。
因此,它将尝试布置嵌套的RecyclerView中的每个视图。这意味着,如果该嵌套项目包含大量项目,那么您的应用程序将遇到严重问题。
除非为Android系统提供更多可能知道如何测量子级的信息,否则应该避免嵌套此类视图。