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
更多相关文章
- Android Studio:xxx is not an enclosing class 错误的解决方法
- 【Android】Android 发送短信和打电话的方法
- Android中AutoCompleteTextView的特殊使用方法
- Android 解决fragment replace方法低效的问题
- android 修改系统各种类型的声音的默认值和最大最小值
- Android中WARNING: Application does not specify an API level
- Android开发SDK版本号和API level对照表,到Android 10.0
- 使用android中的handler延迟执行方法