Android:requestLayout()调用不正确

Android:requestLayout()调用不正确,android,performance,android-listview,Android,Performance,Android Listview,当我尝试在列表视图中膨胀布局时,会发生以下错误: requestLayout() improperly called by android.widget.TextView{...} during layout: running second layout pass 我正试图在列表视图中为布局充气,如下所示: @Override public View getView(int position, View convertView, ViewGroup parent) { if(conve

当我尝试在
列表视图中膨胀布局时,会发生以下错误:

requestLayout() improperly called by android.widget.TextView{...} during layout: running second layout pass
我正试图在
列表视图中为布局充气,如下所示:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if(convertView == null){
        LayoutInflater inflater = (LayoutInflater) musicActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.list_item, parent, false);
        ...
    }else{...}
}
正在膨胀的布局看起来像下面这样简单,但仍然会产生错误

<TextView
    android:id="@+id/txt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="@dimen/txt_size"/>

基于此,我认为XML本身不是问题,除非它与我使用的是ViewPager和片段这一事实有关,请尝试从XML中去掉textSize并在Java代码中进行设置。我认为这会导致布局两次。

问题是,当适配器的方法
getView()
显示布局时,其他一些代码试图访问此视图以显示布局,从而导致冲突


请注意,一些可能您不关心的方法(如
setScale()
setTypeFace()
)确实调用了
requestLayout()
,因此在您的充气语句之后您所做的事情会很有趣。

如果您使用的是ListView的第三方扩展,则可能会发生这种情况。用标准ListView替换它,并检查它是否仍然抛出错误


我也有类似的问题。请检查并回答我的问题。

这个问题似乎是android实现中的一个bug,请参阅:

通过
ListView在代码中激活
ListView
的快速滚动功能。setFastScrollEnabled(true)
将触发此错误,您将开始看到

android.widget.TextView{…}未正确调用requestLayout() 布局期间:运行第二个布局过程

在您的控制台中显示消息

这个bug一定是在KitKat(4.4.x)的一个更新中引入的,因为我在KitKat(4.4.0)的初始版本中没有看到它。除了从上面发出的带有调试消息的丑陋的控制台垃圾邮件外,似乎没有其他影响(在某些情况下可能是性能,我还没有测试)

干杯

PS:这不是第一次对快速滚动功能进行窃听,例如,KitKat 4.4.3中修复了63545,但随后出现了75516-->似乎是谷歌最头疼的话题;-)

2015年5月12日编辑:

几分钟前,我将Nexus7更新为Android 5.1(之前运行的是5.0),在这个新版本中,我不再看到这个问题。由于FastScroll指示器的外观在5.1中也发生了变化,我认为谷歌已经解决了这个问题,或者至少已经注释掉了那些向控制台发送垃圾信息的丑陋线条


&仍然是“未解决的”,但我想它们指的是同一个问题,现在在5.1中已解决。

我通过在XML中的ListView上禁用fastScroll解决了这个问题

<ListView
    android:id="@+id/mListview"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"

    android:fastScrollEnabled="false"
/>

我对摩托罗拉X上的Kitkat 4.4.4和Genymotion有同样的问题。在我的例子中,列表项是一个简单的CheckedTextView,错误发生在AppCompatCheckedTextView中

作为一个正常的实现,我从XML布局文件中扩展了该项,如下所示:

if (convertView == null) {
  convertView = inflater.inflate(R.layout.checkable_list_entry, parent, false);
}
经过一番尝试,我发现这与XML膨胀有关。我不知道根本原因,但作为一种解决方案,我决定按代码扩大列表项,并按代码设置所有属性

结果是这样的:

CheckedTextView view;
if (convertView == null) {
  view = new CheckedTextView(parent.getContext());
  view.setMinHeight(getResources().getDimensionPixelSize(R.dimen.default_touch_height));
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    view.setTextAppearance(R.style.SectionEntry);
  } else {
    view.setTextAppearance(parent.getContext(), R.style.SectionEntry);
  }
  view.setBackgroundResource(R.drawable.form_element);
  view.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
  view.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT));
} else {
  view = (CheckedTextView) convertView;
}
    mHolder.txt_fword.setTextSize(22);
    mHolder.txt_farth.setTextSize(22);
    mHolder.txt_fdef.setTextSize(22);
    mHolder.txt_fdef2.setTextSize(22);
    mHolder.txt_frem.setTextSize(22);
    //if (fdef2.get(pos).equals("")) mHolder.txt_fdef2.setVisibility(View.GONE);        
    //if (frem.get(pos).equals("")) mHolder.txt_frem.setVisibility(View.GONE);

在我的例子中,此警告阻止按钮在API 21设备中显示。按钮可见性以前设置为“消失”

我得到的唯一解决办法是将其设置为不可见,而不是API 21。这不是一个真正的解决方案,但对我来说是可以接受的

我之所以发布这篇文章,是因为它可能对某些人有用

if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
    theButton.setVisibility(View.INVISIBLE);
}
else {
    theButton.setVisibility(View.GONE);
}
在我的例子中(三星Galaxy S4,API 21),这发生在带有EditText的ListView中。我有一个用于字段验证的侦听器。比如:

edit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            error.setVisibility(View.INVISIBLE);
            error.setText("");
        } else {
            String s = edit.getText().toString();
            if (s.isEmpty()) {
                error.setText("Error 1");
            } else if (s.length() < 2 || s.length() > 100) {
                error.setText("Error 2");
            }
            error.setVisibility(View.VISIBLE);
        }
    }
});

这不是一个好的解决方案,但至少它打破了无限循环。

对我来说,这个问题是在调用
setLayoutParams()
时发生的。解决方案在活套上发布了runnable:

//java
imageView.post(新的Runnable(){
@重写公共void run(){
imageView.setLayoutParams(参数);
}
});
//kotlin
post(可运行{imageView.setLayoutParams(params)})

有时您可能已经修复了该问题,但它仍然保留相同的错误,因此您需要关闭visual studio,然后从项目中删除所有bin和obj文件夹,然后从emulator中卸载应用程序。那么,瓦拉!!一切正常

我在相同的警告日志中遇到问题:

requestLayout() improperly called by android.support.v7.widget.AppCompatTextView {...} during layout: running second layout pass
我正在使用recylcerview,并打算用新数据更新它。
唯一适合我的解决方案如下:

步骤(1)。删除当前数据:

public void removeAll() {
    items.clear(); //clear list
    notifyDataSetChanged();
}
步骤(2)。如果要使用新数据填充recyclerview,请首先将新的LayoutManager再次设置为recyclerview:

private void initRecycleView() {
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false));
}
步骤(3)。使用新数据更新recyclerview。例如:

public void refreshData(List newItems) {
    this.items = newItems;
    notifyItemRangeChanged(0, items.size());
}

我这样解决了这个问题:

CheckedTextView view;
if (convertView == null) {
  view = new CheckedTextView(parent.getContext());
  view.setMinHeight(getResources().getDimensionPixelSize(R.dimen.default_touch_height));
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    view.setTextAppearance(R.style.SectionEntry);
  } else {
    view.setTextAppearance(parent.getContext(), R.style.SectionEntry);
  }
  view.setBackgroundResource(R.drawable.form_element);
  view.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
  view.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT));
} else {
  view = (CheckedTextView) convertView;
}
    mHolder.txt_fword.setTextSize(22);
    mHolder.txt_farth.setTextSize(22);
    mHolder.txt_fdef.setTextSize(22);
    mHolder.txt_fdef2.setTextSize(22);
    mHolder.txt_frem.setTextSize(22);
    //if (fdef2.get(pos).equals("")) mHolder.txt_fdef2.setVisibility(View.GONE);        
    //if (frem.get(pos).equals("")) mHolder.txt_frem.setVisibility(View.GONE);

问题是.setVisibility(View.GONE),更改为.setVisibility(View.VISIBLE)

谢谢你的建议!不幸的是,这不起作用,请看我的更新。这有什么好运气?我面临着同样的问题:(不幸的是,没有-因为这只是一个警告,我可能会遗憾地忽略它。
内部的first if块中还发生了什么?它通过ViewHolder重用视图看看这个。花了最后一个小时试图解决这个问题。关闭快速滚动,消息就消失了。至少我知道这不是我想要的d、 感谢您提供的信息。是否有任何解决方案可以删除此日志?我正在尝试将我的
ImageView
大小保留在
onSaveInstanceState
中,此时出现此错误并使我的应用程序崩溃。不确定如何修复此日志,但此答案比“这是一个错误”更具描述性,非常感谢。因此,对我来说,这不是滚动问题。如果你想使用快速滚动,我认为这不是一个解决方案。我可能也有同样的问题,但该链接已断开。编辑:通过以下方式解决:
imageView.post(新运行
    mHolder.txt_fword.setTextSize(22);
    mHolder.txt_farth.setTextSize(22);
    mHolder.txt_fdef.setTextSize(22);
    mHolder.txt_fdef2.setTextSize(22);
    mHolder.txt_frem.setTextSize(22);
    //if (fdef2.get(pos).equals("")) mHolder.txt_fdef2.setVisibility(View.GONE);        
    //if (frem.get(pos).equals("")) mHolder.txt_frem.setVisibility(View.GONE);