膨胀视图以供 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.inflate
和 LayoutInflator.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 的封装,主要是为了混淆问题。
inflate(int resource, ViewGroup root, boolean attachToRoot)
为视图充气。将 attachToRoot
设置为 false
。这会告诉充气机父级不可用。查看http://www.doubleencore.com/2013/05/layout-inflation-as-intended/ 以获得对此问题的精彩讨论,特别是最后的“每个规则都有例外”部分。
【讨论】:
【参考方案3】:你应该使用AlertDialog.Builder.setView(your_layout_id)
,所以你不需要膨胀它。
创建对话框后使用AlertDialog.findViewById(your_view_id)
。
使用(AlertDialog) dialogInterface
在OnClickListener
中获取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_dialog
的A
的属性变量中。【参考方案4】:
将 null 转换为 ViewGroup 解决了警告:
View dialogView = li.inflate(R.layout.input_layout,(ViewGroup)null);
其中li
是LayoutInflater'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 错误:找不到文件以供依赖参考