Предупреждение «Избегайте передачи null в качестве корня представления» при расширении представления для использования AlertDialog

126

Я получаю предупреждение о ворсе, Avoid passing null as the view rootкогда надуваю представления с помощью nullas parent, например:

LayoutInflater.from(context).inflate(R.layout.dialog_edit, null);

Однако представление должно использоваться как содержимое AlertDialog, используя setViewon AlertDialog.Builder, поэтому я не знаю, что следует передавать как parent.

Как вы думаете, что parentдолжно быть в этом случае?

Рэнди Сугианто 'Юку'
источник
2
Передайте false вместо null. увидеть это
MrDumb
Попробуйте указать родительский макет вместо null, а затем не используйте setView.
Haresh Chhelana
Я подавляю предупреждение о ворсинах для этого метода. Я еще не видел веской причины, почему я не должен пройти null.
323go
4
Я понимаю, что проблема макета зависит от родительского представления, но на самом деле это не относится к AlertDialog, который по существу плавает над иерархией представлений Activity. Вот почему вы можете пройти null. Есть причина, по которой вы можете подавить ворс. Lint должен предупреждать вас о часто упускаемых проблемах; в данном случае это правильный вызов.
323go
1
@ ashutiwari4 Я каждый день узнаю что-то новое .. прекрасный мир: Я
Рахул

Ответы:

175

Используйте этот код для расширения диалогового окна без предупреждения:

View.inflate(context, R.layout.dialog_edit, null);
Эдвард Брей
источник
7
@ MarianPaździoch Потому что это не вызывает предупреждения. :-) Конечно, что возникает вопрос о том, почему ворса кода лечит View.inflateи по- LayoutInflator.inflateдругому. Я не видел однозначного ответа. Это может быть связано с тем, почему существует два, казалось бы, эквивалентных способа раздуть одно и то же представление, для чего я также не видел обоснования.
Эдвард Брей,
12
Это не верно. Это только подавляет предупреждение, но проблема все еще существует. Прочтите possiblemobile.com/2013/05/layout-inflation-as-intended для лучшего решения.
jcsahnwaldt Reinstate Monica
16
@JonaChristopherSahnwaldt Не могли бы вы уточнить? В статье говорится, что у AlertDialog должен быть нулевой родительский элемент, потому что у него нет корневого представления. Мне кажется, это подтверждает, что предупреждение имеет смысл для представлений вне диалога, но не применимо для диалогового представления.
Эдвард Брей
7
@EdwardBrey Вы правы - я не читал статью досконально. В данном конкретном случае можно использовать либо View.inflate(...null)или @SuppressLint. В общем, LayoutInflater.from(...).inflate(..., parent, false)лучше. Спасибо за указание на это!
jcsahnwaldt Reinstate Monica
1
@Bevor, который избегает передачи нулевого вопроса, касается случаев, когда у вас есть родитель. Этот вопрос касается того AlertDialog, что не предоставляет родительский элемент для расширяемого представления. При раздутии корневого представления объекта AlertDialogпередача null является правильной. Lint не учитывает этот конкретный контекст, поэтому предупреждение, которое он выдает, если вы используете функцию, которая принимает parentложное срабатывание, не указывает на что-либо, подверженное ошибкам. Вот почему в этом случае допустимо использовать функцию, которая не принимает parentи не вызывает предупреждения.
Эдвард Брей
35

Вкратце, когда вы увеличиваете представление для диалогового окна, оно parentдолжно иметь значение null, поскольку оно не известно во время наполнения представления. В этом случае у вас есть три основных решения, чтобы избежать предупреждения:

  1. Подавить предупреждение с помощью @Suppress
  2. Раздуйте представление с помощью метода надувания представления . Это просто оболочка для LayoutInflater, которая в основном просто запутывает проблему.
  3. Накачать View с помощью LayoutInflater в полный метод : inflate(int resource, ViewGroup root, boolean attachToRoot). Установите attachToRootзначение. falseЭто означает, что надувной элемент недоступен. В более старых версиях Android Lint это удалило предупреждение. В версиях Android Studio после 1.0 это уже не так.

Посетите http://www.doubleencore.com/2013/05/layout-inflation-as-intended/, где подробно обсуждается этот вопрос, в частности, в конце раздела «Каждое правило имеет исключение».

emerssso
источник
19

Приведение к нулю как ViewGroup разрешило предупреждение:

View dialogView = li.inflate(R.layout.input_layout,(ViewGroup)null);

где liнаходится LayoutInflater'sобъект.

СВЛ Нарасимхам
источник
где li - объект LayoutInflater.
SVL Narasimham
3
Это лучший ответ, если вы понимаете, ПОЧЕМУ вы на самом деле это делаете. Краткая история, как вы, возможно, уже читали, заключается в том, что AlertDialog не знает своего родителя во время инфляции, и поэтому побочным эффектом является то, что lint выдает предупреждение в этой конкретной ситуации, когда вы действительно делаете правильные вещи.
Mar Bar
Я прочитал бесчисленное количество ответов и страниц об этом предупреждении, но ваше решение, безусловно, лучшее: простое и элегантное
Couitchy
9
Но это
лишний
11
Затем мы получаем еще одно предупреждение: "Приведение в действие избыточно"!
Mousa
17

Вы должны использовать AlertDialog.Builder.setView(your_layout_id), поэтому вам не нужно его надувать.

Используйте AlertDialog.findViewById(your_view_id)после создания диалога.

Используйте, (AlertDialog) dialogInterfaceчтобы попасть dialogвнутрь, OnClickListenerа затем dialog.findViewById(your_view_id).

Джеффри Чен
источник
1
Это путь! Просто создайте диалог, а затем найдите свое представление.
user1806772
1
Это хороший способ сделать это, однако помните, что этот метод был добавлен в API 21
Николас Карраско
Что, если мы должны сохранить этот раздутый макет в какой-то переменной? Например, я написал класс, Aв котором есть метод onCreateDialog. В последнем я написал, как вы сказали alert_dialog_builder.setView(R.layout.edit_account_dialog);. Но я должен сохранить этот раздутый макет в Aпеременной атрибута с именем the_inflated_layout_of_the_dialog.
JarsOfJam-Scheduler
9

parentДля диалогового окна указывать не нужно .

Подавите это, используя @SuppressLint("InflateParams")в верхней части переопределения.

kjdion84
источник
7

Когда у вас их действительно нет parent(например, создание представления для AlertDialog), у вас нет другого выбора, кроме как пройти null. Итак, сделайте это, чтобы избежать предупреждения:

final ViewGroup nullParent = null;
convertView = infalInflater.inflate(R.layout.list_item, nullParent);
Мусса
источник
4
Он выдает еще одно предупреждение: «value 'nullParent' всегда равно null».
mallaudin 06
Что касается AndroidStudio 3.3 и API 28, это единственное решение, которое работает.
zeeshan
1
  1. Насколько мне известно, AlertDialog - это единственный случай, когда вы можете безопасно использовать null вместо родительского представления. В этом случае вы можете подавить предупреждение, используя:

    @SuppressLint ( "InflateParams")

  2. В общем, вы никогда не должны использовать SupressLint или один из обходных путей, упомянутых в других ответах, чтобы избавиться от предупреждения. Родительское представление необходимо для оценки параметров макета, которые объявлены в корневом элементе расширяемого представления. Это означает, что если вы используете null вместо родительского представления, все параметры макета в корневом элементе будут проигнорированы и заменены параметрами макета по умолчанию. В большинстве случаев это нормально, но в некоторых случаях это приводит к действительно трудно обнаруживаемой ошибке.

Apfelsaft
источник
0

В документации View.inflate()говорится

Раздуть представление из ресурса XML. Этот удобный метод является оболочкой для LayoutInflaterкласса, который предоставляет полный набор опций для просмотра инфляции.

  @param context The Context object for your activity or application.
  @param resource The resource ID to inflate
  @param root A view group that will be the parent.  Used to properly inflate the  layout_* parameters.
Дивья Гупта
источник
0

Согласно https://developer.android.com/guide/topics/ui/dialogs

Раздуйте и установите макет для диалогового окна.
Передайте null в качестве родительского представления, потому что он входит в макет диалогового окна.

поэтому для создания AlertDialog я использую @SuppressLint("InflateParams")

LayoutInflater inflater = requireActivity().getLayoutInflater();
@SuppressLint("InflateParams")
View view = inflater.inflate(R.layout.layout_dialog, null);
builder.setView(view);
Cor
источник
-1

Вместо того, чтобы делать

view = inflater.inflate(R.layout.list_item, null);

делать

view = inflater.inflate(R.layout.list_item, parent, false);

Он раздувает его с помощью данного родителя, но не прикрепляет к нему.

Большое спасибо Coeffect ( ссылка на его пост )

Кристиан
источник
Также было бы полезно знать, как завести родителей.
Йохан Карлссон