在项目中存在卡顿。卡顿的原因是主线程做了耗时任务,xml绘制太复杂,关于耗时任务哪些方法产生了耗时这个已经列出来了,从分析trace来看,在绘制一帧时。有很多线程在跟主线程竞争资源,导致一帧绘制不完整,需要优化线程的调度,分析app,发现线程调度存在问题。
在下面这段代码中:
合并的代码
IMapService mapService = GdServiceFactory.getInstance().getService(IMapService.class);
Observable.fromAction(() -> {
if (poiBean.getLayerType() == BizSearchTypePoiChildPoint) {
SearchLayerController.getInstance().clearAllItems1(MapId.getAmapId(mapId), BizSearchTypePoiLabel);
MapId amapId = MapId.getAmapId(mapId);
SearchLayerController.getInstance().clearFocus1(amapId, BizSearchTypePoiParentPoint);
SearchLayerController.getInstance().clearFocus1(amapId, BizSearchTypePoiChildPoint);
SearchLayerController.getInstance().clearFocus1(amapId, BizSearchTypePoiLabel);
SearchLayerController.getInstance().clearFocus1(amapId, BizSearchTypePoiEndAreaPolygon);
SearchLayerController.getInstance().clearFocus1(amapId, BizSearchTypePoiAlongRoute);
mapService.fitMapOffset1(mapId);
} else {
// Parent POI contains child POI common POI, and polygon bounds, need clear them.
resetPoi(mapId);
mapService.fitMapOffset1(mapId);
}
MapId amapId = MapId.getAmapId(mapId);
// If the parent POI layer type is BizSearchTypePoiLabel, show common POI marker.
if (poiBean.getLayerType() == BizSearchTypePoiLabel) {
BizPointBusinessInfo point = new BizPointBusinessInfo();
point.id = poiBean.getId();
point.mPos3D.lon = poiBean.getPoint().lon;
point.mPos3D.lat = poiBean.getPoint().lat;
SearchLayerController.getInstance().updateSearchPoiLabel1(amapId, point);
}
// Set the marker as focused state
CmLogger.i(GemLevel.D, "setFocus layerType:" + poiBean.getLayerType() + " id:" + poiBean.getId());
SearchLayerController.getInstance().setFocus1(amapId, poiBean.getLayerType(), poiBean.getId(), true);
if (!poiBean.getChildPois().isEmpty()) {
showChildPoi(amapId, poiBean);
}
if (!poiBean.getPoiAoiBounds().isEmpty() || TextUtils.isEmpty(poiBean.getZoomRectString())) {
showPolygonBoundsAndFitZoomLevel(mapId, poiBean);
} else {
mapService.setMapCenter1(mapId, poiBean.getPoint().lon, poiBean.getPoint().lat, 0, true, true);
}
}).compose(RxCompose.bizThread()).subscribe();
分开的代码
Observable.fromAction(() -> {
mapService.setMapCenter1(mapId, poiBean.getPoint().lon, poiBean.getPoint().lat, 0, true, true);
}).compose(RxCompose.bizThread()).subscribe();
Observable.fromAction(() -> {
SearchLayerController.getInstance().setFocus1(amapId, poiBean.getLayerType(), poiBean.getId(), true);
}).compose(RxCompose.bizThread()).subscribe();
Observable.fromAction(() -> {
mapService.fitMapOffset1(mapId);
}).compose(RxCompose.bizThread()).subscribe();
RxCompose.bizThread() 是确保线程不切换,合并的代码是将多个任务放入一个Observable.fromAction()中,,并使用.compose(RxCompose.bizThread())时,不会发生线程切换,在同一个线程操作,没有线程切换开销
为每个任务使用了单独的Observable.fromAction(),并且每个任务都经过.compose(RxCompose.bizThread()),由于RxCompose.bizThread()保证不会发生线程切换,这些任务依然会在同一个线程上执行
多个任务合并时,cpu的体现如下:
NAVI_BIZ_THREAD 运行在cpu1上,主线程运行在cpu3上,不会进行cpu切换,NAVI_BIZ_THREAD 不会与主线程争抢任务
在任务分开始,cpu的体现如下:
主线程运行在cpu3上,NAVI_MAIN_MAP_T 即运行在cpu1上,也运行了cpu3,进行了cpu切换
上面的结果表明单个Observable.fromAction()调用更高效,多个操作放入一个流中执行,不需要触发多次调度
多个Observable.fromAction()调用,即使在同一个线程执行,频繁的创建Observable和调用调度会增加调度开销,从而导致上下文切换,因为每个Observable都会被视作一个新的任务流。