android - 添加许多 Overlay 后 MapView 平移和缩放速度很慢

标签 android performance overlay android-mapview panning

所以我花了很多时间试图弄清楚如何加快速度,但我现在没有主意了。我有一个类 mapPopup,其中一个 MapView 显示在整个屏幕上。 mapPopup 中有一个由 GeoPoint 组成的数组,我想在数组的二维中的每个 GeoPoint 之间画线。我已经使用扩展 Overlay 的自定义类 mapOverlay 完成了这项任务,但我遇到的问题是,一旦绘制了所有 map 叠加层, map 缩放或平移非常慢。一旦将所有叠加层添加到 map 中,通常会有 2000 多个叠加层,但它们都非常小。

考虑到如果叠加层越少 map 会工作得更快,我将所有线绘制到三个单独的叠加层而不是每条线单独的叠加层。这实际上导致 map 的平移和缩放变慢,所以我又回到了许多小的叠加层。

如果能提供一些信息丰富且易于理解的方法说明,我将不胜感激,我可以使用这些方法来加快 map 绘制速度。潜在方法的伪代码或真实代码也可以帮助我更好地理解它。我的代码贴在下面。再次请注意,我的覆盖图和 map 显示正确;我只想要一种允许更快平移和缩放的方法。

mapOverlay 类

public class mapOverlay extends Overlay {

private Projection projection;
private GeoPoint gp1;
private GeoPoint gp2;
private int color;

public mapOverlay(int color, MapView map, GeoPoint geo1, GeoPoint geo2) {
    // super();
    this.projection = map.getProjection();
    this.gp1 = geo1;
    this.gp2 = geo2;
    this.color = color;
}

public void draw(Canvas canvas, MapView mapv, boolean shadow) {
    super.draw(canvas, mapv, false);

    Paint mPaint = new Paint();
    mPaint.setDither(true);
    mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(4);
    mPaint.setColor(this.color);

    Point p1 = new Point();
    Point p2 = new Point();
    Path path1 = new Path();

    projection.toPixels(gp1, p1);
    projection.toPixels(gp2, p2);
    path1.moveTo(p1.x, p1.y);
    path1.lineTo(p2.x, p2.y);
    canvas.drawPath(path1, mPaint);

}

}

mapPopup 类

public class mapPopup extends MapActivity {

public String[] trailNames;
public String tableName = "";
public int numTrails = 0;
public static GeoPoint[][] geoPoints;
public int[] colors = new int[] { Color.WHITE, Color.BLUE, Color.CYAN,
        Color.RED, Color.YELLOW, Color.MAGENTA, Color.GRAY, Color.LTGRAY };
public int[] newColors;
// public Bitmap b;
public GeoPoint firstP;

public void loadMapData(Bitmap b, MapView map, int[] colors,
        GeoPoint[][] GPAA, int ZoomLevel) {
    // GPAA holds an array of an array of GeoPoint
    Log.i("DEBUG", "starting loadMapDataTask");

    map.setSatellite(true);
    MapController mc = map.getController();

    mapOverlay[][] mapOverlay = new mapOverlay[GPAA.length][];
    Log.i("DEBUG", "length of GPAA is: " + GPAA.length);

    // i cycles through the first dimension of GPAA
    for (int i = 0; i < GPAA.length; i++) {
        GeoPoint[] geoPoints = GPAA[i];
        int length = geoPoints.length - 1;
        mapOverlay[i] = new mapOverlay[length]; //
        int pointCount = 0;
        // z cycles through the second dimension of GPAA
        for (int z = 0; z < length; z++) {
            mapOverlay[i][z] = new mapOverlay(colors[i], map,
                    geoPoints[pointCount], geoPoints[pointCount + 1]);
            pointCount++;
        }
    }

    // Actually adds overlays to map
    List<Overlay> mapOverlays = map.getOverlays();
    for (int i = 0; i < mapOverlay.length; i++) {
        int length = mapOverlay[i].length;
        Log.i("DEBUG", "Adding map overlays for trail: " + i);
        Log.i("DEBUG", "Length of mapOverlay[i] is: " + length);
        for (int z = 0; z < length; z++) {
            mapOverlays.add(mapOverlay[i][z]);
        }
    }

    mc.animateTo(GPAA[0][0]);
    mc.setZoom(ZoomLevel);
    Rect r = new Rect();
    map.getDrawingRect(r);
    map.invalidate(r);
}

public static class runBGLoad extends
        AsyncTask<bgLoadParam, Integer, GeoPoint[][]> {

    public GeoPoint[][] geoPoints;

    protected GeoPoint[] getGPa(Context context, String name, int ID) {
        File file = context.getFileStreamPath(name);
        if (file.exists() == false) {
            Log.i("DEBUG", "Creating file");
            InputStream is;
            FileOutputStream fos;

            try {
                Log.i("DEBUG", "id is " + ID);
                is = context.getResources().openRawResource(ID);
                byte[] buffer = new byte[is.available()];
                is.read(buffer);
                fos = context.openFileOutput(name, Context.MODE_PRIVATE);
                fos.write(buffer);
                fos.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        } else {
            Log.i("DEBUG", "File already exists");
        }

        // Log.i("DEBUG", "starting to get geopoints");

        List<Location> gpsPoints = XMLParser.getPoints(file);

        int i = 0;
        int index = 0;

        GeoPoint[] geoPoints = new GeoPoint[gpsPoints.size()];

        // makes list of gpsPoints into GeoPoint[]
        ListIterator<Location> it = gpsPoints.listIterator();

        while (it.hasNext()) {
            index = it.nextIndex();
            Location loc = gpsPoints.get(index);
            geoPoints[i] = new GeoPoint((int) (loc.getLatitude() * 1E6),
                    (int) (loc.getLongitude() * 1E6));
            it.next();
            i++;
        }

        return geoPoints;
    }

    @Override
    protected GeoPoint[][] doInBackground(bgLoadParam... params) {

        Context context = params[0].getContext();
        int tNLength = params[0].getTNames().length;
        geoPoints = new GeoPoint[tNLength][];

        for (int i = 0; i < params[0].getTNames().length; i++) {
            String modName = params[0].getTNames()[i].toLowerCase()
                    .replace(' ', '_');
            int identifier = context.getResources().getIdentifier(modName,
                    "raw", context.getPackageName());
            geoPoints[i] = getGPa(params[0].getContext(), modName
                    + "_mapfile", identifier);
        }
        Log.i("DEBUG", "TEST");
        mapPopup.geoPoints = geoPoints;
        Log.i("DEBUG", "TEST2");
        return geoPoints;
    }

    @Override
    protected void onPostExecute(GeoPoint[][] result) {
        Log.i("DEBUG", "The points are loaded.");
        mapPopup.geoPoints = result;
    }
}

@Override
public void onCreate(Bundle savedInstanceState) {
    Intent intent = getIntent();
    String[] extras = intent.getStringArrayExtra("strings");

    tableName = extras[1];
    numTrails = Integer.parseInt(extras[2]);
    trailNames = intent.getStringArrayExtra("trailNamesA");

    super.onCreate(savedInstanceState);
    setContentView(R.layout.map_popup_layout);

    newColors = new int[numTrails];
    for (int i = 0; i < numTrails; i++) {
        newColors[i] = colors[i];
    }
    ViewGroup layout = (ViewGroup) findViewById(R.id.map_popup);
    TextView[] tVs = new TextView[numTrails];

    for (int i = 0; i < numTrails; i++) {
        LayoutParams params = new RelativeLayout.LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        tVs[i] = new TextView(getApplicationContext());
        tVs[i].setText(trailNames[i]);
        tVs[i].setId(i + 700);
        tVs[i].setTextColor(colors[i]);
        tVs[i].setBackgroundColor(Color.BLACK);

        if (i > 0) {
            params.addRule(RelativeLayout.BELOW, (699 + i));
        }

        layout.addView(tVs[i], params);
    }

}

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);

    MapView map = (MapView) findViewById(R.id.popupMV);
    Bitmap b = Bitmap.createBitmap(map.getWidth(), map.getHeight(),
            Bitmap.Config.RGB_565);

    try {
        trailsActivity.mapPreLoad.get();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }

    loadMapData(b, map, newColors, geoPoints, 17);
}

@Override
protected boolean isRouteDisplayed() {
    // TODO Auto-generated method stub
    return false;
}

}    

最佳答案

我目前面临同样的问题,我刚刚找到了一个解决方法:防止在缩放或平移时绘制叠加层。这并不完美,我仍在寻找更好的解决方案,但至少 map 可以使用,而无需为每次平移或缩放等待 5 秒。

这是我在 Overlay 扩展中使用的代码。它不是 Java 而是 C#(使用 Monodroid)——但它应该很容易理解。

public override bool OnTouchEvent (MotionEvent e, Android.GoogleMaps.MapView mapView)
{
    if (e.Action == MotionEventActions.Down)
        _mustDraw = false;
    else if (e.Action == MotionEventActions.Up)
        _mustDraw = true;
    return base.OnTouchEvent (e, mapView);
}

public override void Draw (Android.Graphics.Canvas canvas, Android.GoogleMaps.MapView mapView, bool shadow)
{
    if (shadow || !_mustDraw)
        return;
    // ...
}

该解决方案适用于每个基于 map 触摸的 Action ,现在执行速度很快,我只是在使用内置缩放控件放大或缩小时缺少相同行为的实现,但我首先需要解决一些问题我在做这部分之前的错误,我稍后会回来讨论这部分。

关于android - 添加许多 Overlay 后 MapView 平移和缩放速度很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10944749/

相关文章:

java - 如何在 Java Swing 中重叠面板?

html - 在 flexbox 容器 div 中覆盖/悬停一个 div

android - 谷歌地图 v2 android 方法 getMap() 返回 null

javascript - 如何存储从 Phonegap/Android 应用程序拍摄的照片

android - 如何有效调用 AES/ECB 64k 次?

performance - 为什么Docker在Raspberry上将我的容器的CPU使用率限制为100%

sql - 事务脚本也是 NoSQL 数据库的反模式吗?

android - 哪个启动器正在运行?

java - 接收带有 2 个数组的 JSON 对象

android - 我怎样才能制作一个指向道路方向的谷歌地图地面叠加层