避免将 null 作为视图根传递(需要在膨胀布局的根元素上解析布局参数)

Posted

技术标签:

【中文标题】避免将 null 作为视图根传递(需要在膨胀布局的根元素上解析布局参数)【英文标题】:Avoid passing null as the view root (need to resolve layout parameters on the inflated layout's root element) 【发布时间】:2014-09-10 00:49:03 【问题描述】:

为 root studio 传递 null 会给我这个警告:

它在getGroupView 中显示一个空值。请帮忙。

public class ExpandableListAdapter extends BaseExpandableListAdapter 

    private Context _context;
    private List<String> _listDataHeader; // header titles
    // child data in format of header title, child title
    private HashMap<String, List<String>> _listDataChild;

    public ExpandableListAdapter(Context context, List<String> listDataHeader,
                                 HashMap<String, List<String>> listChildData) 
        super();
        this._context = context;
        this._listDataHeader = listDataHeader;
        this._listDataChild = listChildData;
    

    @Override
    public Object getChild(int groupPosition, int childPosititon) 
        return this._listDataChild.get(this._listDataHeader.get(groupPosition))
                .get(childPosititon);
    

    @Override
    public long getChildId(int groupPosition, int childPosition) 
        return childPosition;
    

    @Override
    public View getChildView(int groupPosition, final int childPosition,
                             boolean isLastChild, View convertView, ViewGroup parent) 

        final String childText = (String) getChild(groupPosition, childPosition);

        if (convertView == null) 
            LayoutInflater infalInflater = (LayoutInflater) this._context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = infalInflater.inflate(R.layout.list_item, null);


        

        TextView txtListChild = (TextView) convertView
                .findViewById(R.id.lblListItem);

        txtListChild.setText(childText);
        return convertView;
    

    @Override
    public int getChildrenCount(int groupPosition) 
        return this._listDataChild.get(this._listDataHeader.get(groupPosition))
                .size();
    

    @Override
    public Object getGroup(int groupPosition) 
        return this._listDataHeader.get(groupPosition);
    

    @Override
    public int getGroupCount() 
        return this._listDataHeader.size();
    

    @Override
    public long getGroupId(int groupPosition) 
        return groupPosition;
    

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded,
                             View convertView, ViewGroup parent) 
        String headerTitle = (String) getGroup(groupPosition);
        if (convertView == null) 
            LayoutInflater infalInflater = (LayoutInflater) this._context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = infalInflater.inflate(R.layout.list_group, null);
        

        TextView lblListHeader = (TextView) convertView
                .findViewById(R.id.lblListHeader);
        lblListHeader.setTypeface(null, Typeface.BOLD);
        lblListHeader.setText(headerTitle);

        return convertView;
    

    @Override
    public boolean hasStableIds() 
        return false;
    

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) 
        return true;
    


【问题讨论】:

【参考方案1】:

而不是做

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

convertView = infalInflater.inflate(R.layout.list_item, parent, false);

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

【讨论】:

@Coeffect 但是从 Activity 中充气时应该使用什么?我应该用什么代替父母? @AlexanderKuznetsov 取决于你想要做什么,我想。如果您尝试设置活动的内容,您应该使用setContentView(layoutId)。如果您尝试向现有 ViewGroup 添加新视图,您可能应该只传递父视图并让充气器附加新视图。 @LucasTan 我想我会在 TabContentFactory 中保留对 TabHost 的引用,并在充气时将其用作父级,但我不确定这是否是最佳解决方案。奇怪的是 createTabContent 方法不提供父/上下文。 在为InputMethodService 实现onCreateInputView() 时会出现同样的问题(没有父级)。 alertdialog 的自定义视图怎么样,parent 应该是什么?【参考方案2】:

我发现了一篇关于LayoutInflater 的好文章。作者解释了inflate方法的所有版本是如何工作的,并给出了ListViewAlertDialog的例子

http://www.doubleencore.com/2013/05/layout-inflation-as-intended/

更新 #1。

这个答案最近也帮助了我。 https://***.com/a/5027921/1065835

【讨论】:

【参考方案3】:

来吧,由于某种原因,使用 View.inflate 而不是从 layoutinflater 膨胀会使 lint 错误消失。 我想我会在这里发布这个帖子,因为这个帖子在谷歌搜索的顶部......

view = View.inflate(context,R.layout.custom_layout,null);

【讨论】:

这消除了 Lint 警告,但不是问题本身,因为 View.inflate() 在后台调用 LayoutInflater。您应该修复原因,而不仅仅是删除消息。【参考方案4】:

编辑:

在撰写此答案时,我不知道 Lint 抑制。最好抑制 Lint 而不是欺骗 IDE。在行或方法上方添加:

@SuppressLint("InflateParams")

旧答案:

当你真的没有parent 时(例如为AlertDialog 创建视图),除了传递null 之外别无他法。所以这样做是为了避免警告:

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

【讨论】:

与其欺骗 lint 工作,不如进行抑制。 我不确定这个答案是否正确。我成功使用了ViewGroup root = (ViewGroup) myActivity.findViewById(R.id.my_main_content);,其中my_main_content 是我的活动布局文件中最外层容器的ID。 要禁止这个 Lint,在你的方法上方添加 @SuppressLint("InflateParams") 我发现@ban-geoengineering 回复是最有帮助的,它既消除了消息又解决了问题。这是对我有用的 Kotlin 解决方案。 val rootView = findViewById&lt;ViewGroup&gt;(R.id.container) .... imageHolder = vInflater.inflate(R.layout.recycler_view_target, rootView,false) 这让我可以在 RecyclerView Holder 中放置不同的视图。【参考方案5】:

AlertDialog可以使用下面的代码

convertView = layoutInflater.inflate(R.layout.list_item, findViewById(android.R.id.content), false);

【讨论】:

【参考方案6】:

我在寻找解决此问题的方法时发现了一个很好的信息。根据 Dave Smith 的说法,

布局膨胀是在 Android 上下文中使用的术语,用于指示 XML 布局资源何时被解析并转换为 View 对象的层次结构。

这里要求ViewGroup 作为 inflate 方法参数的一部分用于继承更高级别的样式。虽然传递 null 看起来无害,但它实际上可能会在以后给您的应用程序带来严重问题。阅读更多关于此here 的信息。

【讨论】:

【参考方案7】:

这是一张供参考的图片:

return inflater.inflate(R.layout.some_layout, container, true); 
// for the last parameter use true, false or simply don't declare

【讨论】:

顺便...导入ANDROIDX.fragment.app.Fragment;

以上是关于避免将 null 作为视图根传递(需要在膨胀布局的根元素上解析布局参数)的主要内容,如果未能解决你的问题,请参考以下文章

无条件布局,来自视图适配器的膨胀:应该使用 View Holder 模式

为膨胀的布局设置视图的可见性消失

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

如何使用Android自定义视图中的属性设置调整膨胀布局的大小?

用于从布局中膨胀视图的 iOS 模拟 (xib)

java 片段将重用以前膨胀的根视图,这可以节省内存。好可怜 ......