2012-06-08 42 views
4

所以我花了很多時間試圖弄清楚如何加快速度,但我現在已經沒有想法。我有一門課,mapPopup,其中MapView顯示在整個屏幕上。在mapPopup中有一個GeoPoint陣列,我想在陣列的第二維中的每個GeoPoint之間畫線。我已經完成了這項任務,已經使用自定義類mapOverlay,它擴展了Overlay,但是我遇到的問題是,一旦繪製了所有地圖疊加層,地圖縮放或平移都非常緩慢。一旦所有覆蓋圖都添加到地圖中,通常會超過2000個,但它們都非常小。添加了多個覆蓋圖後,MapView平移和縮放速度很慢

考慮到如果覆蓋圖較少,地圖工作會更快,我將所有線條繪製爲三個獨立的疊加層,而不是每行的獨立疊加層。這實際上導致了對地圖的縮放和縮放,所以我恢復了許多小的覆蓋。

我希望我能用一些方法來提高地圖的描述速度。僞代碼或潛在方法的實際代碼也可以幫助我更好地理解它。我的代碼發佈在下面。請再次注意,我的疊加層和地圖顯示正確;我只想要一種方法可以實現更快的平移和縮放。

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

}  

回答

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

該解決方案適用於每一個地圖,基於觸摸的動作,現在執行與良好的速度,我或縮小使用內置變焦控制縮放時,只是缺乏執行相同的行爲,但我首先需要在做這個部分之前去打擊我的一些錯誤,我稍後會回到這個部分。

+3

這幫了我不少。我用MotionEvent.ACTION_MOVE替換了MotionEvent.ACTION_DOWN,並使用了mustDraw = true的else塊。像我的應用程序一樣魅力,讓平移更舒適。 – gelupa

+0

同樣的思路也能以某種方式應用於ItemizedOverlay嗎? – topwik

+0

@towpse:從來沒有使用過這個,但是因爲它擴展了'overlay',我看不出爲什麼它不對。 – psycho