膨胀视图以供 AlertDialog 使用时出现“避免将 null 作为视图根传递”警告

Posted

技术标签:

【中文标题】膨胀视图以供 AlertDialog 使用时出现“避免将 null 作为视图根传递”警告【英文标题】:"Avoid passing null as the view root" warning when inflating view for use by AlertDialog 【发布时间】:2014-12-11 20:27:38 【问题描述】:

当使用 null 将视图膨胀为 parent 时,我收到了 lint 警告 Avoid passing null as the view root,例如:

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

但是,视图将用作AlertDialog 的内容,在AlertDialog.Builder 上使用setView,所以我不知道应该传递什么作为parent

你认为parent在这种情况下应该是什么?

【问题讨论】:

传递 false 而不是 null。见this 尝试给你父布局而不是 null 然后不要使用 setView。 我禁止该方法的 lint 警告。我还没有找到不应该通过null 的充分理由。 我理解布局问题取决于父视图,但这并不真正适用于本质上浮动在 Activity 视图层次结构之上的 AlertDialog。这就是为什么你可以通过null。您可以抑制 lint 是有原因的。 Lint 应该为您经常遗漏的问题提供警告;在这种情况下,它是正确的调用。 @ashutiwari4 我每天都在学习新事物......美丽的世界:我 【参考方案1】:

使用此代码在没有警告的情况下扩展对话框视图:

View.inflate(context, R.layout.dialog_edit, null);

【讨论】:

@MarianPaździoch 因为它不会引起警告。 :-) 当然,这引出了为什么 lint 代码对 View.inflateLayoutInflator.inflate 的处理方式不同的问题。我还没有看到明确的答案。这可能与为什么有两种看似等效的方法可以夸大同一个视图有关,而我也没有看到理由。 这是错误的。它只会抑制警告,但问题仍然存在。阅读possiblemobile.com/2013/05/layout-inflation-as-intended 以获得更好的解决方案。 @JonaChristopherSahnwaldt 你能详细说明一下吗?文章说 AlertDialog 应该有一个 null 父级,因为它没有根视图。对我来说,这似乎强化了警告对对话框外的视图有意义,但不适用于对话框视图。 @EdwardBrey 你是对的——我没有仔细阅读这篇文章。在这种特殊情况下,可以使用View.inflate(...null)@SuppressLint。一般来说,LayoutInflater.from(...).inflate(..., parent, false) 更好。感谢您指出这一点! @Bevor Avoid passing null 的问题是关于您有父母的情况。这个问题是关于AlertDialog,它没有为被膨胀的视图提供父级。在扩展 AlertDialog 的根视图时,传递 null 是正确的。 Lint 没有考虑到这个特定的上下文,因此如果您使用将parent 误报的函数,它会给出警告,而不是表示任何容易出错的迹象。这就是为什么在这种情况下使用不接受 parent 并且不触发警告的函数是有效的。【参考方案2】:

简短的故事是,当您为对话框膨胀视图时,parent 应该为空,因为在视图膨胀时它是未知的。在这种情况下,您可以通过三种基本解决方案来避免该警告:

    使用@Suppress 抑制警告 使用 View 的 inflate method 为 View 充气。这只是一个 LayoutInflater 的封装,主要是为了混淆问题。 使用 LayoutInflater 的 full method: 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/ 以获得对此问题的精彩讨论,特别是最后的“每个规则都有例外”部分。

【讨论】:

【参考方案3】:

你应该使用AlertDialog.Builder.setView(your_layout_id),所以你不需要膨胀它。

创建对话框后使用AlertDialog.findViewById(your_view_id)

使用(AlertDialog) dialogInterfaceOnClickListener 中获取dialog,然后使用dialog.findViewById(your_view_id)

【讨论】:

这是要走的路!只需创建对话框,然后找到您的视图。 这是一个很好的方法,但是请记住这个method 是在 API 21 中添加的 如果我们必须将这个膨胀的布局存储在某个变量中怎么办?例如,我写了一个类A,其中有方法onCreateDialog。在后者中,我按照你所说的alert_dialog_builder.setView(R.layout.edit_account_dialog); 写了。但我必须将这个膨胀的布局存储在名为the_inflated_layout_of_the_dialogA 的属性变量中。【参考方案4】:

将 null 转换为 ViewGroup 解决了警告:

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

其中liLayoutInflater's 对象。

【讨论】:

其中 'li' 是 LayoutInflater 对象。 这个答案是最好的,只要你明白你为什么要这样做。正如您可能已经读过的那样,短篇小说是 AlertDialog 在膨胀时不知道其父级,因此当您实际上在做正确的事情时,lint 在这种精确情况下会引发警告,这是一个副作用。 但它是多余的铸造 然后我们收到另一个警告“铸造是多余的”! 你在开玩笑吗?【参考方案5】:

您无需为对话框指定parent

使用覆盖顶部的@SuppressLint("InflateParams") 来抑制这种情况。

【讨论】:

【参考方案6】:

当您真的没有任何parent(例如为AlertDialog 创建视图)时,您别无选择,只能传递null。所以这样做是为了避免警告:

final ViewGroup nullParent = null;
convertView = infalInflater.inflate(R.layout.list_item, nullParent);

【讨论】:

它会产生另一个警告“值 'nullParent' 始终为空。” 从 AndroidStudio 3.3 和 API 28 开始,这是唯一可行的解​​决方案。【参考方案7】:

根据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);

【讨论】:

【参考方案8】:

    据我所知,AlertDialog 是您可以安全地使用 null 而不是父视图的唯一情况。在这种情况下,您可以使用以下命令抑制警告:

    @SuppressLint("InflateParams")

    一般来说,您永远不应该使用 SupressLint 或其他答案中提到的解决方法之一来消除警告。父视图是评估在被膨胀视图的根元素中声明的布局参数所必需的。这意味着如果您使用 null 而不是父视图,则根元素中的所有布局参数都将被忽略并被默认布局参数替换。大多数时候它会很好,但在某些情况下会导致一个非常难以发现的错误。

【讨论】:

【参考方案9】:

Android 的文档 (AlertDialog) 说:

如果您想显示更复杂的视图,请查找名为“custom”的 FrameLayout 并将您的视图添加到其中:

FrameLayout fl = findViewById(android.R.id.custom);
fl.addView(myView, new LayoutParams(MATCH_PARENT, WRAP_CONTENT));

因此,在我们的例子中,我们可以使用fl 作为父级:

FrameLayout fl = findViewById(android.R.id.custom);
View view = LayoutInflater.from(context).inflate(R.layout.custom_dialog, fl, false);

它有效,但我不确定它是否有效

【讨论】:

【参考方案10】:

而不是做

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

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

它会使用给定的父级对其进行膨胀,但不会将其附加到父级。

非常感谢 Coeffect (link to his post)

【讨论】:

知道如何获得父母也很有用。【参考方案11】:

来自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.

【讨论】:

以上是关于膨胀视图以供 AlertDialog 使用时出现“避免将 null 作为视图根传递”警告的主要内容,如果未能解决你的问题,请参考以下文章

回收视图膨胀不同的行:- 绑定数据时出现异常

Android:膨胀布局时出现带有 InvocationTargetException 的 ***Error

使用 SenchaCmd 构建时出现 SenchaTouch 错误:找不到文件以供依赖参考

片段对话框中的片段膨胀引发错误“片段未创建视图”

我可以在不膨胀/重新膨胀布局的情况下将视图添加到滚动视图吗?

使用通用登录视图时出现“名称'django'未定义”错误?