Почему бы нам не обернуть каждый включенный макет Android XML в пару <merge>?
В качестве продолжения этого вопроса я не могу представить себе вескую причину, по которой мне не следует оборачивать каждый включенный макет XML в <merge>
пара.
Что заставляет меня задуматься, почему команда ADT просто не сделала это поведением по умолчанию?
Есть ли случаи, когда никто не хотел бы такого поведения?
Кстати, объяснение в документации Android по <merge>
тег хуже формулировки в худших юридических соглашениях:
<merge />
Этот тег помогает исключить избыточные группы представлений в иерархии представлений при включении одного макета в другой. Например, если ваш основной макет является вертикальнымLinearLayout
в котором два последовательных вида могут быть повторно использованы в нескольких макетах, тогда макет многократного использования, в котором вы размещаете два вида, требует своего собственного корневого представления. Однако, используя другойLinearLayout
как корень для многоразового макета приведет к вертикальнойLinearLayout
внутри вертикалиLinearLayout
, ВложенныеLinearLayout
не служит никакой реальной цели, кроме как для снижения производительности вашего интерфейса.
Ромен, ты где?
1 ответ
Основное назначение include
тег (как я его понимаю) позволяет разработчику создавать повторно используемые компоненты xml, которые будут использоваться несколько раз в одной и той же операции и / и во многих действиях в приложении. Чтобы этот повторно используемый компонент был действительно полезным, он должен быть самодостаточным и иметь как можно меньше внешних подключений. С моей точки зрения, если бы вы использовали merge
тег в каждом включенном макете это снизит полезность include
пометить в целом. Вот пример, почему я думаю, что это произойдет:
Учтите, что вы хотите реализовать многоразовый ActionBar
XML-компонент для встраивания в каждое из ваших действий. Он будет содержать TextView
и Button
расположен горизонтально. Макет для этого будет:
R.layout.actionbar
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/actionbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/actionbar_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Теперь предположим, что у вас есть два действия в вашем приложении, один, где корневое представление является LinearLayout
(ориентация по вертикали) и тот, где корневой вид RelativeLayout
, Вышеуказанная схема может быть легко включена в LinearLayout
(просто положите его туда, где вы хотите), то же самое будет возможно с RelativeLayout
Конечно, принимая во внимание текущие элементы из этого RelativeLayout
(имейте в виду, что вы должны установить layout_width/height
(например, реплицируется из корня включенного макета) для include
пометка для другого layout_*
атрибуты, которые необходимо учитывать).
Теперь примите во внимание ваше предложение. Макет станет:
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
<TextView
android:id="@+id/actionbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/actionbar_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</merge>
Глядя на наши ActionBar
макет не говорит нам так много, у вас просто есть TextView
и Button
быть включенным где-то. Теперь рассмотрим деятельность, где корень ориентирован вертикально LinearLayout
, Расположение R.layout.actionbar
не может быть просто включен, так как это сломает наш ActionBar
нам нужно добавить дополнительный LinearLayout
(с горизонтальной ориентацией) для нашего макета, чтобы он выглядел как хотелось. Как вы можете видеть, вы находитесь в ситуации выше (макет без merge
тегом), но теперь вы должны помнить, чтобы обернуть включенный макет в LinearLayout
с горизонтальной ориентацией, где когда-либо родительский корень LinearLayout
с ориентацией по вертикали.
Все становится еще хуже, когда корень RelativeLayout
, вы не можете просто использовать include
пометить с merge
в RelativeLayout
(хороший вопрос для чтения Как заставить RelativeLayout работать со слиянием и включением?). Опция, опять же, чтобы вставить include
в LinearLayout
что ставит вас в ситуацию без merge
тег (но теперь добавляет больше проблем, чем решение). Также чтение последней части по этой ссылке http://code.google.com/p/android/issues/detail?id=2863 может выявить другие ошибки, связанные с include
тег.
Как вы можете видеть из моего примера выше, имея merge
тег по умолчанию может привести к некоторым проблемам в определенной ситуации. Также текущая система представляет более последовательный способ работы с макетами (вы должны создать макет для include
тег, как вы создаете нормальные макеты с рутом View
). Так же merge
Тег - это оптимизация, и я не думаю, что вы должны пытаться оптимизировать, пока не начнете видеть некоторые проблемы с производительностью (или вы действительно хотите выжать каждую последнюю потерю производительности за счет сложности). Большинство приложений будут хорошо работать с текущей системой, глубокий макет на три-четыре уровня с приличным количеством просмотров мог бы жить без merge
оптимизация без проблем вообще.
Еще одна проблема с merge
теги в том, что раздутый макет, который имеет merge
поскольку его корень требуется, чтобы присоединиться к родителю, когда надут. Если бы вы были надуть R.layout.actionbar
макет, то вам нужно будет прикрепить его к родителю:
View actionBar = getLayoutInflater().inflate(R.layout.actionbar, root, true);
Я не знаю, является ли это реальным ограничением, может быть, в какой-то редкой ситуации это может нарушить условия сделки.
Просто мое мнение о include
- merge
парное использование.