Android 将视图添加到视图组时是否可以跳过onMeasure?
回答 我有一个RelativeLayout,当用户垂直或水平滚动时,我会动态添加视图。我已经推出了自己的ViewRecycler,因为可能有数千个视图可以组成可以滚动的全部内容,但我在任何时候都只显示30个左右。想象一个放大的日历视图 当我添加即将看到的视图时,我遇到了性能问题,在RelativeLayout上调用onMeasure,在它的所有子视图上调用onMeasure。我已经计算了RelativeLayout将有多大的大小,并在其布局参数上设置了它,因此测量视图组是没有必要的,也没有重新测量已经添加了最终大小的视图,新添加的视图对这些视图没有影响 演示此问题的简单示例是向RelativeLayout添加/删除视图,并观察调用onMeasure,尽管它不会影响RelativeLayout的大小或其他视图的位置 main.xmlAndroid 将视图添加到视图组时是否可以跳过onMeasure?,android,layout,viewgroup,Android,Layout,Viewgroup,回答 我有一个RelativeLayout,当用户垂直或水平滚动时,我会动态添加视图。我已经推出了自己的ViewRecycler,因为可能有数千个视图可以组成可以滚动的全部内容,但我在任何时候都只显示30个左右。想象一个放大的日历视图 当我添加即将看到的视图时,我遇到了性能问题,在RelativeLayout上调用onMeasure,在它的所有子视图上调用onMeasure。我已经计算了RelativeLayout将有多大的大小,并在其布局参数上设置了它,因此测量视图组是没有必要的,也没有重新测
<?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;