性能-Android:requestLayout()调用不正确

当我尝试给ListView中的布局充气时,会发生以下错误:

requestLayout() improperly called by android.widget.TextView{...} during layout: running second layout pass

我正尝试在ListView中扩大布局,如下所示:

@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"/>

我调查了类似的问题,但没有找到解决方案,似乎可以解决问题1,问题2,问题3。

有谁知道是什么原因导致这种类型的错误? 有任何故障排除建议吗? 有关更多上下文,请在ViewPager中的Fragment中显示此ListView

更新

这是完整的XML布局(减去一堆属性),仍然会导致问题

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <TextView
    android:id="@+id/txt1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

 <TextView
    android:id="@+id/txt2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

 <TextView
    android:id="@+id/txt3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

<TextView
    android:id="@+id/txt4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

</RelativeLayout>

基于此,我认为XML本身不是问题,除非它与我正在使用ViewPager和Fragments有关

11个解决方案
41 votes

此问题似乎是android实现中的错误,请参阅:[https://code.google.com/p/android/issues/detail?id=75516]

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

android.widget.TextView错误地调用了requestLayout(){...} 布局期间:运行第二个布局遍

控制台中的消息。

该错误一定是在KitKat(4.4.x)更新中引入的,因为我在最初的KitKat(4.4.0)版本中没有看到它。 除了上面显示调试消息的丑陋控制台垃圾邮件外,似乎没有其他影响(在某些情况下可能是性能,我没有测试过)。

干杯

附言:这不是第一次快速滚动功能出现错误,例如 [https://code.google.com/p/android/issues/detail?id=63545,] 63545已在KitKat 4.4.3中修复,但随后弹出了75516->似乎已成为Google的烦恼主题;- )

编辑2015年5月12日:

几分钟前,我将Nexus 7更新为Android 5.1(之前运行的是5.0),并停止在此新版本中看到此问题。 由于FastScroll指示器的外观在5.1中也发生了变化,因此我认为google已解决此问题,或者至少已注释掉了那些泛滥控制台的丑陋线条。

75516和82461仍然是“未解决”的,但我想那些是指同一个问题,现在在5.1中已解决。

darksaga answered 2020-08-11T01:29:06Z
16 votes

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

请注意,有些方法可能根本不涉及您(例如setScale()setTypeFace())确实会调用requestLayout(),因此在执行inflate语句后您会做些有趣的事情。

axl coder answered 2020-08-11T01:29:31Z
7 votes

对我来说,这个问题是在setLayoutParams()呼叫时发生的。 解决方案是在循环器上发布一个可运行的内容,如此处所述

VladimirVip answered 2020-08-11T01:29:51Z
5 votes

我通过在XML的ListView上禁用fastScroll来解决此问题。

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

    android:fastScrollEnabled="false"
/>
Joaquin Iurchuk answered 2020-08-11T01:30:10Z
1 votes

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

我有类似的问题。 请检查Android布局:运行第二个布局通行证和我的答案。

ksarmalkar answered 2020-08-11T01:30:35Z
1 votes

我在Genymotion的Motorola X上使用Kitkat 4.4.4遇到了相同的问题。 在我的情况下,列表项是一个简单的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;
}
Thomas R. answered 2020-08-11T01:31:08Z
1 votes

就我而言,此警告阻止了按钮在API 21设备中显示。 该按钮的可见性先前已设置为“消失”。

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

我只发布此内容,因为它可能对某些人有用。

if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
    theButton.setVisibility(View.INVISIBLE);
}
else {
    theButton.setVisibility(View.GONE);
}
Javier Torón answered 2020-08-11T01:31:37Z
1 votes

In my case (Samsung Galaxy S4, API 21) this happened in ListView with EditTexts. I have a listener for field validation. Something like:

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);
        }
    }
});

在这些EditText之一中设置焦点后,将进行上述检查。 之后,TextView将更改(TextView包含错误消息,并且位于EditText上)。将焦点设置到第二个或第三个EditText导致对第一个EditText的永久请求并返回到当前状态。 应用程序在请求的无限循环中运行(焦点编辑文本1,焦点编辑文本1,焦点3,焦点3,焦点1等)。

我试图设置listView.setFastScrollEnabled(false)。 我也尝试了一些元素的requestLayout(),例如[https://github.com/sephiroth74/HorizontalVariableListView/issues/93]。目前,我使用XML来固定宽度和高度的TextView:

<TextView
    android:id="@+id/error"
    android:layout_width="match_parent" (or "200dp", but not "wrap_content")
    android:layout_height="20dp"
    .../>

经过一些实验,我注意到可以用“ wrap_content”代替20dp的高度。 但是如果文本太长而分成两行,则应用程序再次陷入无限循环。 因此,android:singleLine="true"将有所帮助。 它已被弃用,但令人惊讶的是android:maxLines="1"android:lines="1"并没有帮助,因为它们再次请求布局。最终,我们有了:

<TextView
    android:id="@+id/error"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:singleLine="true"
    android:textColor="#f00"
    android:textSize="20sp"
    tools:text="Error message"/>

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

CoolMind answered 2020-08-11T01:33:13Z
1 votes

我在使用相同的警告日志时遇到了问题:

requestLayout() improperly called by android.support.v7.widget.AppCompatTextView {...} during layout: running second layout pass

我正在使用recyclerview并打算用新数据更新它。


唯一对我有用的解决方案如下:

第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());
}
Ghasem Sadeghi answered 2020-08-11T01:33:55Z
0 votes

尝试从xml中删除textSize并将其设置为Java代码。 我认为这导致其布局两次。

Gabe Sechan answered 2020-08-11T01:34:15Z
0 votes

有时您可能已经解决了该问题,但是仍然存在相同的错误,所以您需要关闭Visual Studio,然后从项目中删除所有bin和obj文件夹,然后从模拟器中卸载应用程序。 然后哇! 一切都会好的

A. Almazidi answered 2020-08-11T01:34:35Z
translate from https://stackoverflow.com:/questions/24598977/android-requestlayout-improperly-called