にパスを描画するためのオーバーレイがありますが、MapView
毎秒約 10 回不必要に再描画されることに気付きました。このdraw
方法では、パスのすべてのセグメントを描画するため、これは簡単に効率の問題になる可能性があります。
このため、オーバーレイのコンテンツをキャッシュし、実際に必要なときに再描画することにしました。つまり、パスが変更されたとき、マップの中心が移動したとき、またはズーム レベルが変更されたときです。
draw
ここで、メソッドのパラメーターの 1 つはCanvas
to draw on です。キャッシュされたビットマップを描画する方法は知っていますが、キャンバスのコンテンツをビットマップにキャッシュする方法がわからないという問題があります。
新しいキャンバスをインスタンス化できません。またsetBitmap
、キャンバスが aにあり、そのメソッドが呼び出された場合HardwareCanvas
にスローするため、呼び出すこともできません。UnsupportedOperationException
要約すると、キャンバスとビットマップがありますが、キャンバスのコンテンツをビットマップにコピーするにはどうすればよいですか?
編集
これは明確にするために私の描画方法です。手動では呼び出しませんが、マップがまったく動いていない場合でも繰り返し呼び出されます
public void draw(Canvas canvas, MapView map, boolean shadow) {
if (shadow) {
// this overlay doesn't need to draw shadows
return;
}
if (paths.isEmpty()) {
// nothing to draw
return;
}
center = map.getMapCenter();
zoomLevel = map.getZoomLevel();
map.getDrawingRect(bounds);
projection = map.getProjection();
maxLevel = map.getMaxZoomLevel();
for (MapPath mp : paths) {
// adjust path width to current zoom
adjustedWidth = mp.getWidth() * zoomLevel / maxLevel;
if (adjustedWidth < MIN_WIDTH_TO_DRAW) {
// path is too thin, avoid drawing it
continue;
}
paint.setStrokeWidth(adjustedWidth);
paint.setColor(mp.getColor());
state = PathState.FIRST_POINT;
path.reset();
for (PathPoint pp : mp.getPoints()) {
if (!pp.shoudAppearAtZoomLevel(zoomLevel)) {
// do not draw this point at this zoom level
continue;
}
// project a geopoint to a pixel
projection.toPixels(pp.getGeoPoint(), point);
inside = isInsideBounds(point, map);
switch (state) {
case FIRST_POINT:
// move to starting point
firstX = point.x;
firstY = point.y;
path.moveTo(firstX, firstY);
break;
case WAS_INSIDE:
// segment is completely or partially on map
path.lineTo(point.x, point.y);
break;
case WAS_OUTSIDE:
if (inside) {
// segment is partially on map
path.lineTo(point.x, point.y);
} else {
// segment is completely off map
path.moveTo(point.x, point.y);
}
break;
}
// update state
state = inside ? PathState.WAS_INSIDE : PathState.WAS_OUTSIDE;
}
// workaround to avoid canvas becoming too big when path is mostly off screen
path.moveTo(firstX, firstY);
// draw this path to canvas
canvas.drawPath(path, paint);
}
super.draw(canvas, map, shadow);
}