title: MapView panning and zooming is slow after adding many Overlays
body: <p>So I've spent a good amount of time attempting to figure out how to speed this up, but I'm out of ideas now. I have a class, <code>mapPopup</code> in which a <code>MapView</code> is displayed over the entire screen. There is an array of an array of <code>GeoPoint</code> in <code>mapPopup</code>, and I want to draw lines between each GeoPoint in the 2nd dimensions of the array. I've accomplished this task already using a custom class, <code>mapOverlay</code>, that extends <code>Overlay</code>, but the problem I am having is that once all the map overlays are drawn, the map is extremely slow to zoom or pan. Once all the overlays are added to the map there are often over 2000, but they are all very small.</p>
  
  <p>Thinking that the map would work more quickly if there were less overlays, I drew all the lines to three seperate overlays instead of a seperate overlay for each line. This actually resulted in SLOWER panning and zooming of the map, so I reverted back to the many small overlays. </p>
  
  <p>I would appreciate some informative and easy to understand descriptions of a method that I could employ to make the map faster. Pseudocode or real code for the potential method would also help me to understand it better. My code is posted below. Once more, please note that my overlays and map display properly; I would just like a method that will allow faster panning and zooming. </p>
  
  <p>mapOverlay class</p>
  
  <pre><code>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);
  
  }
  
  }
  </code></pre>
  
  <p>mapPopup class</p>
  
  <pre><code>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 &lt; 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 &lt; length; z++) {
              mapOverlay[i][z] = new mapOverlay(colors[i], map,
                      geoPoints[pointCount], geoPoints[pointCount + 1]);
              pointCount++;
          }
      }
  
      // Actually adds overlays to map
      List&lt;Overlay&gt; mapOverlays = map.getOverlays();
      for (int i = 0; i &lt; 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 &lt; 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&lt;bgLoadParam, Integer, GeoPoint[][]&gt; {
  
      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&lt;Location&gt; gpsPoints = XMLParser.getPoints(file);
  
          int i = 0;
          int index = 0;
  
          GeoPoint[] geoPoints = new GeoPoint[gpsPoints.size()];
  
          // makes list of gpsPoints into GeoPoint[]
          ListIterator&lt;Location&gt; 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 &lt; 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 &lt; numTrails; i++) {
          newColors[i] = colors[i];
      }
      ViewGroup layout = (ViewGroup) findViewById(R.id.map_popup);
      TextView[] tVs = new TextView[numTrails];
  
      for (int i = 0; i &lt; 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 &gt; 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;
  }
  
  }    
  </code></pre>