我一直在掙扎了一會兒打造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: 2016年10月26日下午3點25分21秒com.example.neutrino.maze.MovingAverageQueueTests buildVsClonePerformanceTest 信息:cloneScanResult:
所以克隆這種方式是10倍以上,即使反射創建實例效果較差。我知道這個測試並不穩健,因爲在編譯時優化已經完成......但是十的因素很難減輕。我也測試了10K次迭代,然後係數甚至達到了100!只是爲了您的信息。
P.S.讓Parcel.obtain()和parcel.recycle走出循環沒有幫助
圍繞測試需求設計似乎很奇怪。包裝我可能需要使用的每個系統api是否還有其他好處? – Brian 2011-04-09 23:29:15
@Brian是的。首先你可以在一個地方交換WifiManager。版本x出來後會發生什麼,並且API有所不同?您必須更改代碼庫中的很多區域。我更新了更多信息的答案。 – Finglas 2011-04-10 11:49:29
啊,是的,隔離可能改變的東西。除非我用抽象來保護自己,否則我無法控制Android API。好決定! – Brian 2011-04-10 14:38:42