Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

Android Retrofit报错NoClassDefFoundError异常

$
0
0

使用Retrofit 2时踩了个坑,自己封装的Retrofit工具在4.4的手机上跑崩了,测试了下机型,发现在Android 5.x以上的手机就不会出现这样的情况,而在Android 4.x手机上这个问题是必现的

错误信息

java.lang.NoClassDefFoundError: retrofit2.Retrofit$Builder

一看到这个错误信息,马上联想到是否是类缺失了,但是这里指向的是Retrofit2.Retrofit$Builder,导入第三方类库怎么还会缺少类呢,而且如果是类缺失,那么在程序编译期间就会报错的,仔细一看是自己眼花了,NoClassDefFoundError错误和ClassNotFoundException经常容易被搞混,这两个错误类型虽然都指的是找不到类,但是差异还是挺大的

ClassNotFoundExceptio

这个错误比较好解决,就是程序找不到指定的class类,就会出现这个问题,通常发生在程序的编译期间

NoClassDefFoundError

这个错误就比较难找了,在程序正常编译后还报这个未找到类的异常,也就是说这个class类在程序的编译阶段并没有缺失,但是在程序运行阶段,无法把它正常的从内存中加载出来,我们通常使用new方法来实例化一个类,如果这个类在程序运行的时候“失踪”了,那么就会抛出这个异常。

    class A {
        public String getMethod(){
            return "method";
        }
    }
    public class B {
        public static void main(String[] args)
        {
            A a = new A();
            System.out.println(a.getMethod());
        }
    }

就比如说,我们有两个类A和B,B调用A中的方法,我们编译好后,实际上是生成了两个.class文件,这个时候如果我们把A.class文件删掉,再运行程序,那么就会出现NoClassDefFoundError异常了。

解决方法

了解了异常产生的原因,就开始对症下药了,居然在编译期间没有出错,那么说明类文件并没有缺失,而是在编译完成后,运行程序时无法正常的获取到Retrofit$Builder类。

在Android中,我们经常会使用到分包方法,即multiDexEnabled,尤其是当我们的程序应用了大量第三方框架的时候,这个参数就更重要了,因为Android中编译的单个.dex文件最多支持65536个方法,而如果大于这个方法数,就需要使用到multiDexEnabled方法对Dalvik可执行文件.dex进行分包了,而在分包的时候就可能把Retrofit需要使用到的方法分到不同的dex文件中,所以问题应该就出在multiDexEnabled的使用上了。

android {
    ...
    defaultConfig {
        ...
        multiDexEnabled true
    }
    ...
}

这个分包方法,是在Android 5.0之后提供的,如果程序运行在5.0以上的手机,版本设置为minSdkVersion 21以上的应用来说,以上这么配置的方式就可以了

而我在程序中指定的最低支持到的版本是API 19,所以为了兼容Android 5.0以下的手机,需要在build.gradle添加个依赖库com.android.support:multidex:1.0.1

android {
    ...
    defaultConfig {
        ...
        multiDexEnabled true
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.1'
}

同时,对于被我们替换的Application类,需要继承的是MultiDexApplication,而不是Application

public class AppApplication extends MultiDexApplication {...}

通过以上的正确方法配置好了之后,再次运行,就没有再报NoClassDefFoundError错误了。

  • 如果你不想继承MultiDexApplication类,而需要继承其它类型的Application类,那么可以通过重写其attachBaseContext方法,在其中
    手动调用 Dalvik 可执行文件分包方法MultiDex.install()
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(context);
        MultiDex.install(this);
    }
  • 如果没有替换Application类,那么就需要在配置文件AndroidManifest.xml中指定<application>标签的name为android.support.multidex.MultiDexApplication
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.text">
    <application
            android:name="android.support.multidex.MultiDexApplication" >
            ...
    </application>
</manifest>

总结

事实上这个错误并不是由于Retrofit本身造成的,而是错误的使用multiDexEnabled方法造成的,对于多Android版本的兼容性处理的不够好,导致出现了上述问题

当应用程序指定了最小支持的版本号时,应该以这个最小版本号为准,最好适配工作,使用兼容包去处理高低版本之间的差异性问题。

作者:zhuwentao2150 发表于2017/8/18 14:49:47 原文链接
阅读:144 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>