导航库充气机为数据类抛出 ClassNotFoundException

Posted

技术标签:

【中文标题】导航库充气机为数据类抛出 ClassNotFoundException【英文标题】:Navigation Library inflator throws ClassNotFoundException for data class 【发布时间】:2019-06-21 06:50:43 【问题描述】:

在导航库版本 alpha09+(使用 alpha11)中,我在导航图中定义为 argType 的一个数据类遇到 ClassNotFoundException。

app:argType="com.package.app.data.model.user.User.Full"

这个类确实存在。降级回 alpha08 时,该问题似乎没有发生。

这是完整的堆栈跟踪:

2019-01-28 10:30:32.028 6970-6970/com.package.app.debug E/androidRuntime: FATAL EXCEPTION: main
Process: com.package.app.debug, PID: 6970
java.lang.RuntimeException: Unable to start activity ComponentInfocom.package.app.debug/com.package.app.ui.MainActivity: android.view.InflateException: Binary XML file line #53: Binary XML file line #53: Error inflating class fragment
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6669)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
 Caused by: android.view.InflateException: Binary XML file line #53: Binary XML file line #53: Error inflating class fragment
 Caused by: android.view.InflateException: Binary XML file line #53: Error inflating class fragment
 Caused by: java.lang.RuntimeException: Exception inflating com.package.app.debug:navigation/navigation_main line 376
    at androidx.navigation.NavInflater.inflate(NavInflater.java:89)
    at androidx.navigation.NavController.setGraph(NavController.java:424)
    at androidx.navigation.NavController.setGraph(NavController.java:406)
    at androidx.navigation.fragment.NavHostFragment.onCreate(NavHostFragment.java:226)
    at androidx.fragment.app.Fragment.performCreate(Fragment.java:2414)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1418)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1684)
    at androidx.fragment.app.FragmentManagerImpl.addFragment(FragmentManager.java:1930)
    at androidx.fragment.app.FragmentManagerImpl.onCreateView(FragmentManager.java:3745)
    at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:120)
    at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:405)
    at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:387)
    at co.lokalise.android.sdk.core.LokaliseLayoutInflater$PrivateWrapperFactory2.onCreateView(LokaliseLayoutInflater.java:362)
    at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:186)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:780)
    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 co.lokalise.android.sdk.core.LokaliseLayoutInflater.inflate(LokaliseLayoutInflater.java:84)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
    at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:469)
    at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
    at com.package.app.ui.MainActivity.onCreate(MainActivity.kt:75)
    at android.app.Activity.performCreate(Activity.java:7136)
    at android.app.Activity.performCreate(Activity.java:7127)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
2019-01-28 10:30:32.031 6970-6970/com.package.app.debug E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6669)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
 Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: com.package.app.data.model.user.User.Full
    at androidx.navigation.NavType.fromArgType(NavType.java:180)
    at androidx.navigation.NavInflater.inflateArgument(NavInflater.java:181)
    at androidx.navigation.NavInflater.inflateArgumentForDestination(NavInflater.java:145)
    at androidx.navigation.NavInflater.inflate(NavInflater.java:120)
    at androidx.navigation.NavInflater.inflate(NavInflater.java:131)
    at androidx.navigation.NavInflater.inflate(NavInflater.java:80)
        ... 41 more
 Caused by: java.lang.ClassNotFoundException: com.package.app.data.model.user.User.Full
    at java.lang.Class.classForName(Native Method)
    at java.lang.Class.forName(Class.java:453)
    at java.lang.Class.forName(Class.java:378)
    at androidx.navigation.NavType.fromArgType(NavType.java:168)
        ... 46 more
 Caused by: java.lang.ClassNotFoundException: Didn't find class "com.package.app.data.model.user.User.Full" on path: DexPathList[[zip file "/system/framework/org.apache.http.legacy.boot.jar", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/base.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_dependencies_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_resources_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_0_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_1_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_2_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_3_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_4_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_5_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_6_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_7_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_8_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_9_apk.apk"],nativeLibraryDirectories=[/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/lib/x86, /system/lib]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        ... 50 more
    Suppressed: java.io.IOException: No original dex files found for dex location /data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_resources_apk.apk
    at dalvik.system.DexFile.openDexFileNative(Native Method)
    at dalvik.system.DexFile.openDexFile(DexFile.java:354)
    at dalvik.system.DexFile.<init>(DexFile.java:101)
    at dalvik.system.DexFile.<init>(DexFile.java:75)
    at dalvik.system.DexPathList.loadDexFile(DexPathList.java:394)
    at dalvik.system.DexPathList.makeDexElements(DexPathList.java:354)
    at dalvik.system.DexPathList.<init>(DexPathList.java:164)
2019-01-28 10:30:32.031 6970-6970/com.package.app.debug E/AndroidRuntime:     at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:74)
    at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:65)
    at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:64)
    at com.android.internal.os.ClassLoaderFactory.createClassLoader(ClassLoaderFactory.java:73)
    at com.android.internal.os.ClassLoaderFactory.createClassLoader(ClassLoaderFactory.java:88)
    at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:74)
    at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:40)
    at android.app.LoadedApk.createOrUpdateClassLoaderLocked(LoadedApk.java:727)
    at android.app.LoadedApk.getClassLoader(LoadedApk.java:810)
    at android.app.LoadedApk.getResources(LoadedApk.java:1032)
    at android.app.ContextImpl.createAppContext(ContextImpl.java:2345)
    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5749)
    at android.app.ActivityThread.access$1100(ActivityThread.java:199)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1650)
            ... 6 more

我已将导航库组件从 alpha08 更新为 alpha11。当他们发布 alpha09 时,我也更新并遇到了同样的问题,并认为这是一个错误,所以我等待。现在,问题仍然存在,我似乎无法弄清楚希望出了什么问题。

我已经禁用 ProGuard 进行调试,以及缩小并启用 Multidex 以查看这是否有帮助。

    debug 
        minifyEnabled false
        useProguard false
        versionNameSuffix '-DEBUG'
        applicationIdSuffix '.debug'
    

该类也已添加到 proguard-rules 中,看看是否可行。

-keep class com.package.app.data.model.**  *;  

就我而言,这应该有效吗? Android Studio 也会像这样为我生成 XML。

提前致谢。

【问题讨论】:

【参考方案1】:

毕竟,这是 Android Studio 中的一个已知错误。

自 1.0.0-alpha09 发布以来,他们处理内部类的方式发生了一些变化。

如果一个 parcelable 是一个内部类,它必须写成: com.domain.app.User$Full 其中 Full 是打包的对象。

如果您想了解更多相关信息,请在 Google 的问题跟踪器上查看此答案:https://issuetracker.google.com/u/2/issues/123614632#comment4

【讨论】:

很遗憾他们仍然没有在官方文档中包含这些信息。 这仍然适用于 nav_version= 2.3.0-alpha02。谢啦!我认为直接从设计中生成参数更容易,而不是在文本模式下手动生成。当我们从文本模式手动编辑 nav_graph.xml 代码并遇到此类问题时,这会有所帮助。 你救了我的命,兄弟 你救我!谢谢【参考方案2】:

刚刚遇到与此问题类似的问题,我意识到我没有设置任何 proguard 规则。以下是可能有用的附加信息。

以下代码在导航组件版本2.2.0-rc02中找到。

// NavType.java
try 
    String className;
    if (type.startsWith(".") && packageName != null) 
        className = packageName + type;
     else 
        className = type;
    

    if (type.endsWith("[]")) 
        className = className.substring(0, className.length() - 2);
        Class<?> clazz = Class.forName(className);
        if (Parcelable.class.isAssignableFrom(clazz)) 
            return new ParcelableArrayType(clazz);
         else if (Serializable.class.isAssignableFrom(clazz)) 
            return new SerializableArrayType(clazz);
        
     else 
        Class<?> clazz = Class.forName(className);
        if (Parcelable.class.isAssignableFrom(clazz)) 
            return new ParcelableType(clazz);
         else if (Enum.class.isAssignableFrom(clazz)) 
            return new EnumType(clazz);
         else if (Serializable.class.isAssignableFrom(clazz)) 
            return new SerializableType(clazz);
        
    
    throw new IllegalArgumentException(className + " is not Serializable or "
            + "Parcelable.");
 catch (ClassNotFoundException e) 
    throw new RuntimeException(e);

您可以看到它使用Class.forName(String) 方法查找类。所以保留他们的名字就足够了。

# Instead of -keep
-keepnames class com.package.app.data.model.**  *; 

如果提供了packageName,您可以从 argType 属性的值中省略包名称,但遗憾的是,如果您根据构建变体使用某些应用程序 id 后缀,它将不起作用。 (所以 不要在 argType 中省略包名

【讨论】:

谢谢谢谢谢谢你为我节省了很多时间。我最终在这里找到了正确的规则:***.com/questions/28563803/… 另见developer.android.com/guide/navigation/…和issuetracker.google.com/issues/139313440【参考方案3】:

我遇到了同样的问题,我的 argType 是片段的子类。我将该类移出片段并修复了问题

【讨论】:

嗨!我已经发布了关于这个问题的正确答案。完全忘记了我的 SO 问题,但它现在就在那里。在 Android 团队的帮助下。

以上是关于导航库充气机为数据类抛出 ClassNotFoundException的主要内容,如果未能解决你的问题,请参考以下文章

ContentDisposition 类抛出不一致的异常

如何使用 Aspectj 捕获和抑制 Java 类抛出的异常

TailwindCSS 为暗模式类抛出错误

Ninject - 如何在构造过程中识别哪个类抛出异常

用户类抛出异常:org.apache.spark.sql.AnalysisException:无法推断 Parquet 的架构。必须手动指定

Apache Spark 2.4.0、AWS EMR、Spark Redshift 和 User 类抛出异常:java.lang.AbstractMethodError