4

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

考虑到如果叠加层较少,地图会更快地工作,我将所有线绘制到三个单独的叠加层,而不是每条线的单独叠加层。这实际上导致地图的平移和缩放速度变慢,所以我恢复到许多小的叠加层。

我将不胜感激一些信息丰富且易于理解的方法描述,我可以用来使地图更快。潜在方法的伪代码或真实代码也将帮助我更好地理解它。我的代码发布在下面。再一次,请注意我的叠加层和地图正确显示;我只是想要一种允许更快平移和缩放的方法。

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;
}

}    
4

1 回答 1

2

I'm currently facing the same problematic, and I just found a workaround : prevent the overlays from drawing when zooming or panning. That's not perfect and I'm still looking for a better solution, but at least the map is usable without waiting 5 seconds for each pan or zoom.

Here is the code I used in my Overlay extension. It's not Java but C# (using Monodroid) - but it should be easily understandable.

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;
    // ...
}

That solution works for every map-touch based action, and now performs with a good speed, I just lack implementation of the same behaviour when zooming in or out using built-in zoom controls, but I first need to fight some of my bugs before doing this part, I'll come back on this part later.

于 2012-06-18T11:24:37.397 回答