我一直在努力构建ScanResult 对象。我已经成功地使用了上面的反射方法。
如果有人正在寻找克隆ScanResult 对象(或任何其他实现Parcelable 接口的对象)的方法,您可以使用这种方法(我在单元测试中检查了它):
@RunWith(RobolectricTestRunner.class)
@Config(manifest=Config.NONE)
public class MovingAverageQueueTests {
@Test
public void parcelTest() {
Parcel parcel = Parcel.obtain();
ScanResult sr = buildScanResult("01:02:03:04:05:06", 70);
parcel.writeValue(sr);
parcel.setDataPosition(0); // required after unmarshalling
ScanResult clone = (ScanResult)parcel.readValue(ScanResult.class.getClassLoader());
parcel.recycle();
assertThat(clone.BSSID, is(equalTo(sr.BSSID)));
assertThat(clone.level, is(equalTo(sr.level)));
assertThat(clone, is(not(sameInstance(sr))));
}
private ScanResult buildScanResult(String mac, int level) {
Constructor<ScanResult> ctor = null;
ScanResult sr = null;
try {
ctor = ScanResult.class.getDeclaredConstructor(null);
ctor.setAccessible(true);
sr = ctor.newInstance(null);
sr.BSSID = mac;
sr.level = level;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return sr;
}
}
至于性能,这个幼稚的检查:
@Test
public void buildVsClonePerformanceTest() {
ScanResult sr = null;
long start = System.nanoTime();
for (int i = 0; i < 1000000; i++) {
sr = buildScanResult("01:02:03:04:05:06", 70);
}
long elapsedNanos = System.nanoTime() - start;
LOGGER.info("buildScanResult: " + elapsedNanos);
start = System.nanoTime();
for (int i = 0; i < 1000000; i++) {
sr = cloneScanResult(sr);
}
elapsedNanos = System.nanoTime() - start;
LOGGER.info("cloneScanResult: " + elapsedNanos);
}
显示了这些结果:
2016 年 10 月 26 日下午 3:25:19 com.example.neutrino.maze.MovingAverageQueueTests buildVsClonePerformanceTest
信息:buildScanResult:202072179
2016 年 10 月 26 日下午 3:25:21 com.example.neutrino.maze.MovingAverageQueueTests buildVsClonePerformanceTest
信息:cloneScanResult:2004391903
因此,即使使用反射,这种方式的克隆效率也比创建实例的效率低 10 倍。我知道这个测试并不稳健,因为在编译时进行了优化......但是很难减轻十倍的影响。我也测试了 10K 次迭代,然后这个因子甚至是 100!仅供参考。
附:让 Parcel.obtain() 和 parcel.recycle 脱离循环并没有帮助