Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 将视图添加到视图组时是否可以跳过onMeasure?_Android_Layout_Viewgroup - Fatal编程技术网

Android 将视图添加到视图组时是否可以跳过onMeasure?

Android 将视图添加到视图组时是否可以跳过onMeasure?,android,layout,viewgroup,Android,Layout,Viewgroup,回答 我有一个RelativeLayout,当用户垂直或水平滚动时,我会动态添加视图。我已经推出了自己的ViewRecycler,因为可能有数千个视图可以组成可以滚动的全部内容,但我在任何时候都只显示30个左右。想象一个放大的日历视图 当我添加即将看到的视图时,我遇到了性能问题,在RelativeLayout上调用onMeasure,在它的所有子视图上调用onMeasure。我已经计算了RelativeLayout将有多大的大小,并在其布局参数上设置了它,因此测量视图组是没有必要的,也没有重新测

回答

我有一个RelativeLayout,当用户垂直或水平滚动时,我会动态添加视图。我已经推出了自己的ViewRecycler,因为可能有数千个视图可以组成可以滚动的全部内容,但我在任何时候都只显示30个左右。想象一个放大的日历视图

当我添加即将看到的视图时,我遇到了性能问题,在RelativeLayout上调用onMeasure,在它的所有子视图上调用onMeasure。我已经计算了RelativeLayout将有多大的大小,并在其布局参数上设置了它,因此测量视图组是没有必要的,也没有重新测量已经添加了最终大小的视图,新添加的视图对这些视图没有影响

演示此问题的简单示例是向RelativeLayout添加/删除视图,并观察调用onMeasure,尽管它不会影响RelativeLayout的大小或其他视图的位置

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/shell"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
</LinearLayout>
运行此操作时,您将看到对onMeasure的两个初始(预期)调用,然后每次单击按钮添加/删除视图时都会看到一个调用。这显然运行得很好,但您可以看到当您有嵌套视图的复杂布局时,对onMeasure的常量调用可能会出现问题


有没有一种推荐的方法可以绕过这些onMeasure调用,或者至少是onMeasure调用measureChildren?

我将onMeasure更改为:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int count = getChildCount();
    for (int i = 0; count > i; i++) {
        View v = getChildAt(i);

        if (v.getVisibility() != GONE) {
            if (v.getMeasuredWidth() <= 0 || v.getMeasuredHeight() <= 0) {
                measureChild(v,
                    MeasureSpec.makeMeasureSpec(v.getLayoutParams().width,
                        MeasureSpec.AT_MOST),
                    MeasureSpec.makeMeasureSpec(v.getLayoutParams().height,
                        MeasureSpec.AT_MOST));
            }
        }
    }

    setMeasuredDimension(resolveSize(staticContainerWidth, widthMeasureSpec),
        resolveSize(staticContainerHeight, heightMeasureSpec));
}

当动画发生在viewgroup的大小上时,我遇到了类似的问题,它的onMeasure()经常被调用。由于父视图包含许多子视图,频繁的级联onMeasure()调用导致动画性能出现问题。我有另一个肮脏的解决方案,但比推出自己的layoutManager要简单得多

long mLastOnMeasurTimestamp;
...
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    ...
    long currentTimestamp = System.currentTimeMillis();
    if(currentTimestamp - mLastOnMeasureTimestamp < SKIP_PERIOD_IN_MILL){
        return;
    }
    mLastOnMeasureTimestamp = currentTimestamp;
    ...
long mlastonemasterimestamp;
...
@凌驾
测量时的保护空隙(内部宽度测量等级、内部高度测量等级){
...
长currentTimestamp=System.currentTimeMillis();
if(当前时间戳-mLastOnMeasureTimestamp<跳过周期){
返回;
}
MLAstoneMasureTimeStamp=当前时间戳;
...

我遇到了类似的问题,我的解决方案是检查尺寸是否已更改:

int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(parentWidth, parentHeight);
if ( mClientWidth == parentWidth && mClientHeight == parentHeight ) {
    return;
}

mClientWidth = parentWidth;
mClientHeight = parentHeight;

因此,如果家长的维度没有真正改变,它就不会被级联到孩子身上。

android开发者回答:感谢Mark的交叉链接。我用我的更快/更脏的解决方案更新了原始帖子。你能以一种有助于他人的方式回答你自己的问题吗?只需编辑掉“解决方案”从您的问题中选择并添加为新答案。一旦您这样做,您可以选择您的答案作为正确答案。这可能看起来很奇怪,但这是处理此类情况的首选方法。完成。谢谢Will,我是一个新手。如果您在最初测量后将一个孩子添加到该家长,新孩子会被测量吗?似乎是这样在这种情况下,是不是…或者我忽略了什么?它对我不起作用,甚至没有显示整个视图。:/scrollView作为父视图使用,setFillViewport(true)…应该可以工作!
long mLastOnMeasurTimestamp;
...
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    ...
    long currentTimestamp = System.currentTimeMillis();
    if(currentTimestamp - mLastOnMeasureTimestamp < SKIP_PERIOD_IN_MILL){
        return;
    }
    mLastOnMeasureTimestamp = currentTimestamp;
    ...
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(parentWidth, parentHeight);
if ( mClientWidth == parentWidth && mClientHeight == parentHeight ) {
    return;
}

mClientWidth = parentWidth;
mClientHeight = parentHeight;