添加许多叠加后,MapView平移和缩放很慢

时间:2012-06-08 07:32:39

标签: android performance overlay android-mapview panning

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

如果覆盖较少,我认为地图可以更快地工作,我将所有线条绘制成三个单独的叠加层,而不是每条线的单独叠加层。这实际上导致了SLOWER平移和缩放地图,所以我又回到了许多小的叠加层。

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

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

}    

1 个答案:

答案 0 :(得分:2)

我目前面临同样的问题,我刚刚找到了解决方法:防止在缩放或平移时绘制叠加层。这并不完美,我仍然在寻找更好的解决方案,但至少可以使用地图而无需等待每个平移或缩放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;
    // ...
}

该解决方案适用于每个基于地图触摸的动作,现在以很快的速度执行,我只是在使用内置缩放控件放大或缩小时缺乏相同行为的实现,但我首先需要对抗一些在做这部分之前我的错误,我稍后会回到这一部分。