64K方法数限制解决办法

随着业务逻辑越来越多,业务模块也越来越大,不可避免会遇到64K方法数的限制。最直观的表现就是编译报错:

较早版本的编译系统中,错误内容如下:

Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536

较新版本的编译系统中,错误内容如下:

trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.

64K限制的原因

Android APK文件本质上是一个压缩文件,它包含的classes.dex文件是可执行的Dalvik字节码文件,这个.dex文件中存放的就是编译后的Java代码。Dalvik可执行文件规范限制了单个.dex文件最多引用的方法数是65536个。其中包含联网Android Framework、APP引用的第三方函数库以及APP自身的方法。

使用MultiDex解决64K限制的问题

Android 5.0之前的版本

Android 5.0之前系统使用的Dalvik虚拟机默认为每个APK只生成一个classes.dex文件,为了规避单个.dex文件超过64K的问题,我们拆分成多个classes.dex文件。启动应用时先加载的classex.dex为主dex文件,其他的为从dex文件。Google推出一个名为MultiDex Support Library的函数库来避免这个问题。

Android 5.0及之后的版本

Android 5.0 之后使用ART来代替Dalvik虚拟机,ART天然支持从APK文件中加载多个.dex文件。在应用安装期间,它会执行一个预编译操作,并将多个单一的.dex文件编译成一个单一的.oat文件,应用运行时区加载这个.oat文件,而不是再去一个一个加载.dex文件。

配置MultiDex

Android Gradle 插件在 Android SDK Build Tools 21.1 及更高版本的编译工具上支持multidex作为编译配置的一部分,所以确保我们的Android SDK Build Tools tools已经更新至21.1或更高版本,然后再来配置应用的multidex部分。

第一步,修改app/build.grale文件,使项目能够使用multidex:

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"  // 这里必须要21.1.0之后
    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 21
        ...
        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

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

第二步,修改AndroidManifest.xml文件,引用MultiDexApplication类:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.yifeng.mdstudysamples">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication"> 
        ...
    </application> 
</manifest>

如果用户继承变重写了Application,可以将继承的Application换成MultiDexApplication。

public class MyApplication extends MultiDexApplication {
    @Override
    public void onCreate() {
        super.onCreate();
    }
}

或者重写attachBaseContext() 方法

@Override
 protected void attachBaseContext(Context base) {
     super.attachBaseContext(base);
     MultiDex.install(this);
}

特别注意,如果没有实现这部分代码,运行时会出现NoClassDefFoundError的错误,尤其是在依赖三方函数库时。

在开发阶段优化MultiDex的构建

multidex会加长构建应用的时间,这个必要的过程可能会拖慢你的开发进度。原因在于构建系统需要经过复杂的计算决定哪些类要包含在主.dex文件中,哪些类可以包含在从dex文件中。 为加速构建过程,我们可以在Gradle中配置productFlavors来创建两个flavor:一个是开发阶段使用的,一个是生产阶段使用的。开发阶段将minSdkVersion改为21使用ART运行时机制,这样能加快构建速度。release时改为合适的minSdkVersion,这样仅在release时费时较长。

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"  // 这里必须要21.1.0之后
    productFlavors{
    // 配置不同的falvor
        dev {
            minSdkVersion 21     // 开发环境的minSdkVersion 
        }
        prod {
            minSdkVersion 14    // 生产环境的minSdkVersion 
        }
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.1'
}
  1. 这里每个module对应的.dex文件不会被合并,因此避免了决定哪些类要放在主dex文件中的耗时计算。
  2. 只能在Android 5.0 设备上进行测试
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在MapReduce编程中,K均值聚类是一个常用的算法。在实验中可能会遇到以下问题: 1. 据倾斜问题 在K均值聚类中,据可能会出现倾斜,导致一些Reducer处理的据量过大,而其他Reducer则处理很少的据。这会导致整个程序运行效率低下。 解决办法:可以采用据切分、据预处理、负载均衡等方法来解决据倾斜问题。比如可以对据进行随机分片,或者采用局部聚类的方法进行预处理,以达到负载均衡的效果。 2. 初始中心点选择问题 K均值聚类算法中,初始中心点的选择对结果有很大的影响。如果初始中心点选择不合理,可能会导致最终的聚类结果不理想。 解决办法:可以采用随机选择、聚类采样等方法来确定初始中心点。同时,可以多次运行算法,选择最优的结果。 3. 算法收敛速度问题 K均值聚类算法需要迭代多次才能收敛,每次迭代都需要进行MapReduce操作,这会导致程序运行时间较长。 解决办法:可以采用优化算法、增加并行度等方法来提高算法收敛速度。比如可以采用Mini-Batch K-means算法来减少计算量,或者增加Reducer的量来提高并行度。 4. 据量过大问题 K均值聚类算法需要处理大量据,如果据量过大,可能会导致程序无法运行或者运行时间过长。 解决办法:可以采用据采样、分布式存储等方法来解决据量过大的问题。比如可以采用Hadoop分布式文件系统(HDFS)来存储据,或者采用MapReduce框架中的Combiner函数来减少据传输量。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值