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

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

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页