RecyclerView#onMeasure() 没有通过调用 setMeasuredDimension() 设置测量尺寸

Posted

技术标签:

【中文标题】RecyclerView#onMeasure() 没有通过调用 setMeasuredDimension() 设置测量尺寸【英文标题】:RecyclerView#onMeasure() did not set the measured dimension by calling setMeasuredDimension() 【发布时间】:2017-12-23 17:20:15 【问题描述】:

我有一个带有RecyclerView 的片段,并附有LinearSnapHelper,以便将视图置于中心并通过缩放其大小来突出显示它。

它工作正常,但是当从 backstack 中弹出这个片段时,它会抛出以下异常。

E/UncaughtException: java.lang.IllegalStateException: View with id 2131689939: android.support.v7.widget.RecyclerView#onMeasure() did not set the measured dimension by calling setMeasuredDimension()
at android.view.View.measure(View.java:19746)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
at android.widget.LinearLayout.measureHorizontal(LinearLayout.java:1117)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:642)
at android.view.View.measure(View.java:19734)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
at android.view.View.measure(View.java:19734)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
at android.view.View.measure(View.java:19734)
at android.support.v4.widget.NestedScrollView.measureChildWithMargins(NestedScrollView.java:1420)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at android.support.v4.widget.NestedScrollView.onMeasure(NestedScrollView.java:482)
at android.view.View.measure(View.java:19734)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at android.view.View.measure(View.java:19734)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.support.design.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:714)
at android.support.design.widget.HeaderScrollingViewBehavior.onMeasureChild(HeaderScrollingViewBehavior.java:90)
at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onMeasureChild(AppBarLayout.java:1391)
at android.support.design.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:784)
at android.view.View.measure(View.java:19734)
at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:1081)
at android.view.View.measure(View.java:19734)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:139)
at android.view.View.measure(View.java:19734)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
at android.view.View.measure(View.java:19734)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at android.view.View.measure(View.java:19734)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
at android.view.View.measure(View.java:19734)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at com.android.internal.policy.DecorView.onMeasure(DecorView.java:687)
at android.view.View.measure(View.java:19734)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2271)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1358)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1607)

RecyclerView is的相关代码为

https://gist.githubusercontent.com/anonymous/81a2ae091ded158839b6353ddb03163f/raw/1aff18064d4de4e42b79aa50ff8d44bd6df365a9/Main.java

【问题讨论】:

你找到什么了吗? 【参考方案1】:

我认为这是因为我们使用 LayoutManager 调用 RecyclerView.setLayoutManager(),而 LayoutManager 已经有 RecyclerView

public void setLayoutManager(LayoutManager layout) 
    ...
    if (layout != null) 
        if (layout.mRecyclerView != null) 
            throw new IllegalArgumentException("LayoutManager " + layout
                    + " is already attached to a RecyclerView:"
                    + layout.mRecyclerView.exceptionLabel());
        
        mLayout.setRecyclerView(this);
        if (mIsAttached) 
            mLayout.dispatchAttachedToWindow(this);
        
    
    ...

但由于我不明白的原因,在 Logcat 中打印的异常是

UncaughtException: java.lang.IllegalStateException: View with id 2131231433: android.support.v7.widget.RecyclerView#onMeasure() did not set the measured dimension by calling setMeasuredDimension()`

也许有什么东西捕获了这个异常并抛出这个异常(没有原因)?

【讨论】:

是的。布局管理器需要重新初始化。谢谢!!【参考方案2】:

我通过简单地调用mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); 解决了这个问题,它有效,我希望它会帮助别人。

【讨论】:

【参考方案3】:

好的,我刚刚按照@Kevin Robatel 提到的那样修复了它。 就我而言,我只在 onCreate() 中初始化布局管理器一次,然后在 onViewCreated() 或 onResume() 中使用它(即在多个地方)。

因此,解决方法是“每次需要设置布局管理器时重新初始化布局管理器”。

这对我来说也是一个减少,干杯!

【讨论】:

【参考方案4】:

就我而言,我有超过 1 个回收站视图,但我只创建了一次线性布局管理器。

我为每个回收站视图创建了线性布局管理器,它工作正常。

谢谢。

【讨论】:

以上是关于RecyclerView#onMeasure() 没有通过调用 setMeasuredDimension() 设置测量尺寸的主要内容,如果未能解决你的问题,请参考以下文章

Android开发实践:为什么要继承onMeasure()

android 自定义View onMeasure中 super.onMeasure 和 setMeasuredDimension

转载深入剖析自定义View之onMeasure

什么时候调用onMeasure方法 Android的onMeasure方法

Andoid自定义View的OnMeasure详解和自定义属性

[Android Pro] Android开发实践:为什么要继承onMeasure()