Кто-нибудь имеет опыт работы с этим?Есть ли способ определить, почему был запущен цикл макета?
Есть способ точно определить, почему цикл макета запущен.
Перейти к макету экрана, который вы хотите отладитьи замените верхний контейнер пользовательским контейнером, который переопределяет только один метод: requestLayout ().
Так, например, если ваш макет выглядит следующим образом:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- omitted for brevity -->
</android.support.v4.widget.DrawerLayout>
Сначала необходимо создать новый пользовательский класс, который является подклассом вашего класса контейнера:
public class RootView extends DrawerLayout {
public RootView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void requestLayout() {
super.requestLayout();
}
}
И тогда вам нужно будет изменить ваш xml:
<?xml version="1.0" encoding="utf-8"?>
<com.example.RootView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- omitted for brevity -->
</com.example.RootView>
Теперь, способ работы Android состоит в том, что, когда любая группа просмотра получает запрос макета, она также вызывает requestLayout () своегопрямой родитель.Это означает, что всякий раз, когда любой вызов requestLayout () выполняется внутри вашего экрана, также будет вызываться requestLayout () вашего RootView.
Так что начните сеанс отладки, поместите точку останова в метод RootView.requestLayout () и выполнитедействие, которое вы думаете, вызывает цикл макета.Посмотрите на трассировку стека.Это всегда будет выглядеть так:
RootView.requestLayout() line: 15
RelativeLayout(View).requestLayout() line: 17364
RelativeLayout.requestLayout() line: 360
FrameLayout(View).requestLayout() line: 17364
... a dozen of other calls to requestLayout() ...
TimeCell(View).requestLayout() line: 17364
TextViewPlus(View).requestLayout() line: 17364
TextViewPlus(TextView).setTypeface(Typeface) line: 2713
... more methods ...
Первый метод, который не является requestLayout (), - это то, что вызывает цикл макета.
В приведенном выше примере это TextViewPlus.setTypeface (Гарнитура).
Возобновив программу и подождав, пока точка останова снова сработает, вы сможете быстро определить все методы, которые запускают ретрансляцию в вашем конкретном случае.
Однако обратите внимание, что интерфейсЛаги почти всегда вызваны вызовами нескольких измерений, а не несколькими циклами компоновки!
В сложной компоновке (представления с прокруткой, линейные компоновки с весами и т. д.) для одного прохода компоновки может потребоваться, чтобы onMeasure быловызывается несколько раз в одном представлении, иногда до 500 раз за цикл макета и более.Чтобы проверить, является ли это вашей проблемой, переопределите методы onMeasure и onLayout одного из нижних представлений (одно из представлений, удаленных от rootView; обратите внимание, что отношение onLayout к onMeasure будет различным для разных представлений на экране).Может быть трудно точно определить, какое представление имеет наихудшее отношение onLayout к onMeasure, но любые представления, которые находятся внутри LinearLayout внутри LinearLayout внутри LinearLayout внутри LinearLayout ... - хорошее место для начала.
Если onMeasure называется moreчем 16 раз за onLayout, то у вас есть проблемы.Попробуйте сделать иерархию представлений более плоской, удалите LinearLayouts с атрибутом weigthSum и ScrollViews.