Android兼容性问题 -- SparseArray.clone()方法异常

本文探讨了Android SparseArray在使用clone()方法时遇到的异常问题,分析了问题原因在于该方法在API Level 14及以上版本才可用,但被错误地标记为从API Level 1支持。这导致在低版本系统上运行时抛出java.lang.NoSuchMethodError。为避免此类异常,建议在代码中进行版本判断,用遍历方式实现对象拷贝作为替代方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android SparseArray

在Android中提供了一组SparseArray类,用来存储key为整数时的key-value值。Android提供的SparseArray类有SparseArray, LongSparseArray, SparseBooleanArray, SparseIntArray和SparseLongArray五种类型。其中SparseArray用来存储key为Integer,value为任意类型的key-value值,LongSparseArray用来存储key为Long,value为任意类型的key-value值,SparseBooleanArray, SparseIntArray和SparseLongArray则分别用来存储key为Integer,value为Boolean,Integer和Long类型的key-value值。
在Eclipse中使用HashMap< Integer, T >定义变量时总是会提示”Use new SparseArray< T >(…) instead for better performance”(在Android Studio中似乎没有看到此提示),也就是说ADT建议使用SparseArray替代HashMap< Integer, T >,以提供更好的性能。当使用其他几种特定key-value类型的HashMap时也会有类似的提示。为了性能考虑,还是采纳ADT的建议,使用SparseArray来代替HashMap。

SparseArray.clone()方法异常

SparseArray系列类提供了一系列用来添加,删除,获取Array元素的方法。其中有一个clone()方法,可以用来生成一个SparseArray对象的拷贝。但是当我们通过试图如下代码去拷贝一个SparseArray对象时
,会发现在部分系统中会抛出java.lang.NoSuchMethodError异常。

SparseArray<String> anotherArray = srcArray.clone();

这里写图片描述

问题原因

查看Android API Level 14(Android 4.0)版本的 api变化(http://developer.android.com/sdk/api_diff/14/changes/),可以看到SparseArray的clone()方法是Android4.0版本中才开始有的,在Android4.0以下的版本中并没有此方法。所以在Android4.0以下的版本中执行SparseArray.clone()就会抛出此异常。
在Android中新的SDK版本中添加新的类和方法是很常见的。在AndroidManifest.xml中会指定minSdkVersion版本,也就是应用需要支持的最低SDK版本。为了避免产生这类在低版本系统中执行高版本才有的api导致的异常,在开发时Android Lint会自动检查在代码中是否使用了高于minSdkVersion版本中的api,如果在项目代码中使用了高于minSdkVersion版本中才有的新的api,会给出一个call new api的Lint Error。
然而不幸的是,google将SparseArray的clone()方法错误的标记为从api level 1就开始支持的api。这导致Android Lint无法检查出SparseArray的clone()方法的调用问题,开发者也无从知道这个api调用会导致的潜在异常。
这里写图片描述
这个问题在Eclipse+ADT和Android Studio中都存在。
此外,由于此处抛出的是NoSuchMethodError,不是NoSuchMethodException,不能通过catch(Exception)来捕获。如果需要捕获此错误,需要用catch(Error),例如

try {
    anotherArray = srcArray.clone();
} catch (NoSuchMethodError e) {
    e.printStackTrace();
}

解决方法

代码中增加判断,如果是Android4.0以下版本,通过遍历方式来实现对象拷贝。例如:

SparseArray<String> anotherArray;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
    anotherArray = srcArray.clone();
} else {
    anotherArray = new SparseArray<>();
    for (int i = 0; i < srcArray.size(); i++) {
        int key = srcArray.keyAt(i);
        String value = srcArray.valueAt(i);
        anotherArray.append(key, value);
    }
}

参考:https://code.google.com/p/android/issues/detail?id=39242

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值