为自定义按钮充气时发生 ClassNotFoundException(适用于 phone;平板电脑异常)

ClassNotFoundException when inflating custom button (works on phone; exception on tablet)

我实现了一个自定义按钮,它在我的 Nexus 5 phone 中可以毫无问题地膨胀。但是,当我尝试在 Samsung Galaxy 平板电脑(甚至是 BQ Edison 平板电脑)中 运行 它时,它会在为 Button 充气时抛出 ClassNotFoundException。

在调试和发布模式下都会抛出异常,无论是否使用混淆器。你知道是什么原因造成的吗?有什么办法可以解决吗?

例外情况:

android.view.InflateException: Binary XML file line #38: Error inflating class com.appx.ui.ExpandedTouchButton
            at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:761)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:769)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:498)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:398)
            at com.appx.ui.animation.HowScreenFragment.onCreateView(HowScreenFragment.java:142)
            at android.app.Fragment.performCreateView(Fragment.java:1700)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:890)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)
            at android.app.BackStackRecord.run(BackStackRecord.java:684)
            at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1453)
            at android.app.FragmentManagerImpl.run(FragmentManager.java:443)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5476)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "com.appx.ui.ExpandedTouchButton" on path: DexPathList[[zip file "/data/app/com.appx-4.apk"],nativeLibraryDirectories=[/data/app-lib/com.appx-4, /vendor/lib, /system/lib]]
            at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:67)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
            at android.view.LayoutInflater.createView(LayoutInflater.java:565)
            at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:702)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:761)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:769)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:498)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:398)
            at com.appx.ui.animation.HowScreenFragment.onCreateView(HowScreenFragment.java:142)
            at android.app.Fragment.performCreateView(Fragment.java:1700)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:890)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)
            at android.app.BackStackRecord.run(BackStackRecord.java:684)
            at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1453)
            at android.app.FragmentManagerImpl.run(FragmentManager.java:443)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5476)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
            at dalvik.system.NativeStart.main(Native Method)

这里是 Java 声明代码:

package com.appx.ui;
public class ExpandedTouchButton extends FrameLayout implements ViewTreeObserver.OnPreDrawListener {
   //...
}

下面是布局 XML 文件中的按钮用法:

<com.appx.ui.ExpandedTouchButton
    android:id="@+id/btnLogIn"
    android:layout_width="240dp"
    android:layout_height="44dp"
    android:layout_gravity="center"
    android:layout_marginTop="0dp"
    android:textSize="20dp"
    android:textColor="@color/text_white"
    android:text="@string/log_in"
    android:background="@drawable/login_button" />

谢谢!


编辑 1

我尝试了以下指令,我从 LayoutInflater.createView() 代码中复制了它,它抛出了 ClassNotFoundException。不管是什么,这似乎是一个 class 加载问题。

Class clazz = getActivity().getClassLoader()
    .loadClass("com.appx.ui.ExpandedTouchButton")
        .asSubclass(View.class);

此外,以下代码抛出 NoClassDefFoundError...

Class clazz = ExpandedTouchButton.class.getClassLoader()
    .loadClass("com.appx.ui.ExpandedTouchButton").asSubclass(View.class);

抱歉,我发布的信息似乎永远无法找到答案。

问题实际上是我启用了多索引 (https://developer.android.com/intl/es/tools/building/multidex.html)。

我没有正确设置 multidexing(即我没有在 Android 清单中将我的应用程序配置为 MultiDexApplication)。因此,我的 Android 5.1.1 的 Nexus 5 能够访问所有 classes,但三星的 4.4.2 平板电脑则不能。我假设平板电脑只在一个 dex 文件中搜索 class 个文件(而不是生成的两个文件)。

我设法通过只导入部分 google 服务库 (com.google.android.gms:play-services-plus:7.5.0) 而不是整个库来减少依赖项的数量。换句话说,我禁用了多索引并且它起作用了