LayoutInflater.from 传参不当引起的android.view.InflateException

1、复现

1.1. 场景

RecyclerView 里面有个楼层使用 android.support.design.widget.TabLayout 作一个 Tab 切使用:android

1.2 问题代码出处

RecyclerView.AdapterOnCreateViewHolder简单返回一个ViewHolder:安全

return new ViewHolder(LayoutInflater
.from(applicationContext).inflate(R.layout.xx, parent, false))
复制代码

这里我使用的是ApplicationContext,由于我一直被教导不要持有activity的引用,so都是Context应该没有什么不一样。bash

1.3 报错

到楼层展现的时候报错:app

android.view.InflateException: 
Binary XML file line #7: 
Error inflating class android.support.design.widget.TabLayout
复制代码

2、查找问题代码

2.1 XML 检查

最早确定是检查 xml 文件里面的类路径是否正确,检查后发现没问题。post

2.2 代码分析

问题报错解析 TabLayout 类的时出错,打断点,发如今该行代码时崩溃(TabLayout代码在不一样版本里相关代码位置会发生微调,本场景是design.28.0.0版本):ui

public TabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    ......
    TypedArray a = ThemeEnforcement.obtainStyledAttributes(...);
    ......
}
复制代码

继续深刻:this

public static TypedArray obtainStyledAttributes(Context context, AttributeSet set, @StyleableRes int[] attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, @StyleableRes int... textAppearanceResIndices) {
    checkCompatibleTheme(context, set, defStyleAttr, defStyleRes);
    .....
}
复制代码

继续深刻:spa

private static void checkCompatibleTheme(Context context, AttributeSet set, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
    ......
    checkAppCompatTheme(context);
}
复制代码

继续深刻:code

public static void checkAppCompatTheme(Context context) {
    checkTheme(context, APPCOMPAT_CHECK_ATTRS, "Theme.AppCompat");
}
复制代码

问题代码找到component

private static void checkTheme(Context context, int[] themeAttributes, String themeName) {
    if (!isTheme(context, themeAttributes)) {
        throw new IllegalArgumentException("The style on this component requires your app theme to be " + themeName + " (or a descendant).");
    }
}
复制代码

跟主题没找到有关。

三. 分析

1. AppcompatActivity

咱们在使用继承该 Activity 时必须使用 Theme.Appcompat 及其子类的主题,否则也会报这个错误。基本问题缘由能够定位为LayoutInflater没有带 theme 去解析。

2. Activity Context 与 Application Context 区别

Look at here:LayoutInflater.from参数Context传Activity、Application区别

归根结底是我传入的是 ApplicationContext,解析时没有带 theme 致使崩溃。

4、总结

一直认为 LayoutInflater.from() 传入应用上下文一劳永逸且安全,在大多数场景下没有问题,能够成功解析,可是对于有 theme 要求的控件,仍是须要使用 activity 传入解析。

相关文章
相关标签/搜索