在膨胀过程中膨胀TextView在方法addFontWeightStyle()上抛出noSuchMethodException

问题描述 投票:8回答:1

更新:我已经更改了标题,删除了ExoPlayer与正在发生的事情有关的指示,因为我已经设法复制了它而没有使用它。

我决定尝试在API级别上隔离此错误:

我获得了运行Android 7.0(Api 24)的旧三星平板电脑(Tab S2),并且没有出现错误。

我无法在使用API​​ 25的Nexus 6仿真器上复制此问题

我还尝试了运行Android 8.0.0(Api 26)的更新的三星平板电脑(Tab S3),与三星S7 Edge手机上的版本相同。我得到了同样的错误。

然后我创建了一个运行Api 26(Oreo 8.0.0)的新仿真器(Pixel 2 XL)并运行该软件并得到了同样的错误。

然后我创建了一个运行Api 27(Oreo 8.1)的新仿真器(Pixel XL)并运行该软件并得到了同样的错误。

试图在Android 9上验证这一点失去了挫折 - 下载捆绑包时出现错误,谷歌搜索发现许多人必须以管理员身份运行以解决此问题,这样做,将下载复制到SDK位置我是使用我的正常登录,在我的正常登录下重新启动Android,从Studio的每个提示修补SDK,并使用9.定义了一个模拟器。得到了相同的错误。

有趣的是,在使用Pie的堆栈跟踪中,我得到了一个不同的行号,用于在TypefaceCompat中发生故障 - 这次是第47行,这至少是相关类的实例化(TypefaceCompatApi28Impl)。然而,堆栈跟踪仍然显示Api21Impl抛出错误。检查Api28Impl向我展示它扩展了Api26Impl,扩展了Api21Impl。所以看起来这只是标签没有被正确报告的问题。 Api21Impl是基类,所以这是报告的内容。

它仍然无法解释错误发生的原因以及该怎么办。

因此,至少从这个有限的测试中可以看出,Oreo 8.0引入了一些问题,此后所有SDK中都存在这个问题。

该怎么办?

更新:其他一些奇怪的事情 - 我的三星是API 26(8.0.0),但下面的堆栈跟踪显示Android正在尝试使用TypefaceCompatApi21Impl:

at androidx.core.graphics.TypefaceCompatApi21Impl.<clinit>(TypefaceCompatApi21Impl.java:74)

TypefaceCompatApi21Impl中的那行代码如下所示:

        try {
            fontFamilyClass = Class.forName(FONT_FAMILY_CLASS);
            fontFamilyCtor = fontFamilyClass.getConstructor();
error here--->            addFontMethod = fontFamilyClass.getMethod(ADD_FONT_WEIGHT_STYLE_METHOD,
                     String.class, Integer.TYPE, Boolean.TYPE);

这有点奇怪的是,在堆栈跟踪的下方,我们看到* Impl类是如何初始化的:

调用AppCompatTextView.setTypeface()方法(第576行)这反过来导致创建一个字体:

finalTypeface = TypefaceCompat.create(getContext(), tf, style);

当调用静态方法create()时,这又会导致运行静态初始化程序:

public class TypefaceCompat {
    private static final TypefaceCompatBaseImpl sTypefaceCompatImpl;
    static {
        if (Build.VERSION.SDK_INT >= 28) {
            sTypefaceCompatImpl = new TypefaceCompatApi28Impl();
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            sTypefaceCompatImpl = new TypefaceCompatApi26Impl();
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
                && TypefaceCompatApi24Impl.isUsable()) {
            sTypefaceCompatImpl = new TypefaceCompatApi24Impl();
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            sTypefaceCompatImpl = new TypefaceCompatApi21Impl();
        } else {
            sTypefaceCompatImpl = new TypefaceCompatBaseImpl();
        }
    }

stacktrace中的这一行:

at androidx.core.graphics.TypefaceCompat.<clinit>(TypefaceCompat.java:49)

实际上是初始化TypefaceCompatApi26Impl()的线,这表明应该使用TypefaceCompatApi26Impl(考虑到我的三星硬件的API级别,这是有道理的)然而堆栈跟踪显示TypefaceCompatApi21Impl()抛出错误!

怎么可能?

这里的另一个线索是静态初始化程序只运行一次。因为我只是在我启动细节布局之后得到这个(但是还有其他布局也在它们之前出现了TextView组件),所以必须有一些与这种布局相关的东西,这在某种程度上是不同的。以下是布局中的前几个组件(直到TextView组件的第一个定义):

<?xml version="1.0" encoding="utf-8"?>
<!-- This layout is used by PlaylistDetailFragment -->
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/item_listitem_constraint_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Layout related to Playlist 'Header' -->
    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintGuide_percent="0.25"
        android:orientation="vertical" />

    <androidx.constraintlayout.widget.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintGuide_percent="0.80"
        android:orientation="vertical" />

    <androidx.constraintlayout.widget.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintGuide_percent="0.90"
        android:orientation="vertical" />

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/item_list_content_image"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter"
        android:layout_marginStart="16dp"
        android:layout_marginTop="4dp"
        android:background="?android:attr/selectableItemBackground"
        android:src="@drawable/playlist"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/guideline1"
        app:layout_constraintBottom_toBottomOf="@+id/playlist_detail_description"/>

    <TextView
        android:id="@+id/playlist_detail_list_content_title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="end"
        android:text="@string/playlist_title_label"
        android:textAppearance="@android:style/TextAppearance.Material.Small"
        app:layout_constraintTop_toTopOf="@+id/playlist_detail_title"
        app:layout_constraintBottom_toBottomOf="@+id/playlist_detail_title"
        app:layout_constraintRight_toRightOf="@+id/playlist_detail_list_content_description"/>

我想也许TextView定义中的android:textAppearance="@android:style/TextAppearance.Material.Small"行由于某种原因导致了问题,但删除它没有任何效果 - 发生同样的错误。

更新2/15/19:这次再次发生,这次是在同一个三星设备上,以前没有发生过,完全不同的布局根本不使用ExoPlayer,实际上只使用库存小部件。在下面的堆栈跟踪中,此行:

at com.reddragon.cloudframe.PlaylistDetailFragment.onCreateView(PlaylistDetailFragment.java:309)

是我在给布局充气的地方:

final View rootView = inflater.inflate(R.layout.playlist_detail, container, false);

布局包括非常标准的项目(TextView,RecyclerView,指南)等。这是完整的堆栈跟踪:

2019-02-15 06:31:12.287 10895-10895/com.reddragon.cloudframe E/TypefaceCompatApi21Impl: java.lang.NoSuchMethodException
    java.lang.NoSuchMethodException: addFontWeightStyle [class java.lang.String, int, boolean]
        at java.lang.Class.getMethod(Class.java:2068)
        at java.lang.Class.getMethod(Class.java:1690)
        at androidx.core.graphics.TypefaceCompatApi21Impl.<clinit>(TypefaceCompatApi21Impl.java:74)
        at androidx.core.graphics.TypefaceCompat.<clinit>(TypefaceCompat.java:49)
        at androidx.core.graphics.TypefaceCompat.create(TypefaceCompat.java:190)
        at androidx.appcompat.widget.AppCompatTextView.setTypeface(AppCompatTextView.java:576)
        at androidx.appcompat.widget.AppCompatTextHelper.loadFromAttributes(AppCompatTextHelper.java:217)
        at androidx.appcompat.widget.AppCompatTextView.<init>(AppCompatTextView.java:103)
        at androidx.appcompat.widget.AppCompatTextView.<init>(AppCompatTextView.java:93)
        at androidx.appcompat.app.AppCompatViewInflater.createTextView(AppCompatViewInflater.java:182)
        at androidx.appcompat.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:103)
        at androidx.appcompat.app.AppCompatDelegateImpl.createView(AppCompatDelegateImpl.java:1267)
        at androidx.appcompat.app.AppCompatDelegateImpl.onCreateView(AppCompatDelegateImpl.java:1317)
        at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:189)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:772)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:866)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
        at com.reddragon.cloudframe.PlaylistDetailFragment.onCreateView(PlaylistDetailFragment.java:309)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2530)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:887)
        at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1233)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1299)
        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:688)
        at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2069)
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1859)
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1814)
        at androidx.fragment.app.FragmentManagerImpl.execSingleAction(FragmentManagerImpl.java:1691)
        at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:537)
        at androidx.fragment.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:170)
        at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1244)
        at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1092)
        at androidx.viewpager.widget.ViewPager.onMeasure(ViewPager.java:1622)
        at android.view.View.measure(View.java:23297)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6928)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:733)
        at com.google.android.material.appbar.HeaderScrollingViewBehavior.onMeasureChild(HeaderScrollingViewBehavior.java:95)
        at com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior.onMeasureChild(AppBarLayout.java:1556)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:803)
        at android.view.View.measure(View.java:23297)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6928)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)

有什么想法吗?这很奇怪,非常令人沮丧!

它似乎在它试图膨胀的第一个TextView上失败,但我无法弄清楚为什么会发生这个错误。我在这个应用程序的其他布局中使用相同的TextView小部件,它们膨胀得很好!

更新2/13/19:当我搜索类似的问题时,我找到了this post。因为它提到了模拟器与物理上的不同行为,我在物理设备(Samsung 7 Edge,Android 8.0.0)上测试了我的问题并且没问题。

编辑2/16/19 - 但现在看到这篇文章顶部的评论。我不知道为什么在我最初的测试中没有发生这种情况,我在这里描述的是我在2月13日所做的,但问题是“退回”在运行API 26的Samsung 7 Edge上。

我删除了之前的模拟器(Nexus 5,API 27),并创建了一个新模拟器(Nexus 6,API 25)和....没有错误!奇怪,但不知何故模拟器让我感到困惑...我觉得如何更快地解决这些问题仍然会很好。

=================================

我一直在使用最新的Exoplayer(2.9.5)开发一个应用程序(MediaPlayerActivity),并且最近刚尝试膨胀库存视图时遇到错误:

2019-02-12 21:36:43.339 25761-25761/E/TypefaceCompatApi21Impl: java.lang.NoSuchMethodException
    java.lang.NoSuchMethodException: addFontWeightStyle [class java.lang.String, int, boolean]
        at java.lang.Class.getMethod(Class.java:2068)
        at java.lang.Class.getMethod(Class.java:1690)
        at androidx.core.graphics.TypefaceCompatApi21Impl.<clinit>(TypefaceCompatApi21Impl.java:74)
        at androidx.core.graphics.TypefaceCompat.<clinit>(TypefaceCompat.java:49)
        at androidx.core.graphics.TypefaceCompat.create(TypefaceCompat.java:190)
        at androidx.appcompat.widget.AppCompatTextView.setTypeface(AppCompatTextView.java:576)
        at androidx.appcompat.widget.AppCompatTextHelper.loadFromAttributes(AppCompatTextHelper.java:217)
        at androidx.appcompat.widget.AppCompatTextView.<init>(AppCompatTextView.java:103)
        at androidx.appcompat.widget.AppCompatTextView.<init>(AppCompatTextView.java:93)
        at androidx.appcompat.app.AppCompatViewInflater.createTextView(AppCompatViewInflater.java:182)
        at androidx.appcompat.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:103)
        at androidx.appcompat.app.AppCompatDelegateImpl.createView(AppCompatDelegateImpl.java:1267)
        at androidx.appcompat.app.AppCompatDelegateImpl.onCreateView(AppCompatDelegateImpl.java:1317)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:772)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:866)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
        at android.view.LayoutInflater.parseInclude(LayoutInflater.java:995)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:859)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
        at com.google.android.exoplayer2.ui.PlayerControlView.<init>(PlayerControlView.java:296)
        at com.google.android.exoplayer2.ui.PlayerView.<init>(PlayerView.java:452)
        at com.google.android.exoplayer2.ui.PlayerView.<init>(PlayerView.java:304)
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:334)
        at android.view.LayoutInflater.createView(LayoutInflater.java:647)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:790)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
        at MediaPlayerActivity$MediaPagerAdapter.instantiateItem(MediaPlayerActivity.java:676)

我正在使用标准库存ExoPlayer视图 - 没有自定义:

pager_video_item.xml中的布局:

<!-- Video Player  -->
<com.google.android.exoplayer2.ui.PlayerView
    android:id="@+id/video_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"/>

错误开始的代码,位于PagerAdapter实例中:

        case Media.MEDIA_TYPE_VIDEO:
            itemView = mLayoutInflater.inflate(R.layout.pager_video_item, container, false);

mLayoutInflater在PagerAdapter构造函数中初始化:

class MediaPagerAdapter extends PagerAdapter {

    final Context mContext;
    final LayoutInflater mLayoutInflater;

    MediaPagerAdapter(Context context) {
        mContext = context;
        mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

传递的上下文来自我的MediaPlayerActivity类,它扩展了androidx.appcompat.app.AppCompatActivityCFViewPager扩展ViewPager,并且只是添加了一些逻辑来适当地处理调度触摸事件。):

mViewPagerView = findViewById(R.id.activity_media_player_viewpager);
((CFViewPager) mViewPagerView).setAdapter(new MediaPagerAdapter(this));

我可以在同一台机器上构建和运行ExoPlayer演示,但它可以工作。很明显我在我的应用程序中更改了一些令运行时混乱的设置。再说一遍,这几天就完美地运作了。

我已经倾倒了版本控制差异,并且无法看到我引入的任何可能导致此行为的内容。

从堆栈跟踪中,当尝试在PlayerControlView中膨胀TextView时,它看起来失败了。但我不知道如何排除故障。

什么会导致运行时“突然”认为它不能使用反射来找到TypefaceCompatApi21Impl.java中的addFontWeightStyle()方法?

Android Studio是最新的稳定版本(3.3.1)我相信我的gradle文件是最新的:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

compileSdkVersion 28
defaultConfig {
    applicationId "mycoolapp.com"
    minSdkVersion 21
    targetSdkVersion 28
    versionCode 1
    versionName "1.0"

构建工具设置为28.0.3

我已经使缓存无效并重新启动,重建等。

感谢您对在何处进行故障排除的任何想法。

android-studio layout-inflater android-inflate nosuchmethoderror android-typeface
1个回答
5
投票

这是已经向Android团队报告过的一个错误,似乎已经为将来的版本做好了准备:

https://issuetracker.google.com/issues/124274577

我猜他们指的是未来的AndroidX库版本。

© www.soinside.com 2019 - 2024. All rights reserved.