web-dev-qa-db-ja.com

Android Googleマップの効率的なマップオーバーレイ

私は次のことをしたいと思っており、数日間これらに固執しています:

  1. ポリラインを描画(ポリラインをエンコードしましたが、デコードできました)マップを移動すると移動します
    私が見つけた唯一の解決策は、ジオポイントを画面座標に変換することでした...マップを移動しても移動しません。

  2. 私はHelloItemizedOverlay を使用して約150個のマーカーを追加しましたが非常に遅くなります
    何をすべきか考えていますか?スレッド(ハンドラー)について考えていました。

  3. ある種の特定の関数を定期的に実行するタイマー関数、たとえば1分ごとに探していました。

  4. すべてのマーカー/ラインからGoogleマップをクリアするなどの方法も探していました。

21
Ahsan

以下の回答:

1)これが私が使用した解決策です:

/** Called when the activity is first created. */
private List<Overlay> mapOverlays;

private Projection projection;  

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    linearLayout = (LinearLayout) findViewById(R.id.zoomview);
    mapView = (MapView) findViewById(R.id.mapview);
    mapView.setBuiltInZoomControls(true);

    mapOverlays = mapView.getOverlays();        
    projection = mapView.getProjection();
    mapOverlays.add(new MyOverlay());        

}

@Override
protected boolean isRouteDisplayed() {
    return false;
}

class MyOverlay extends Overlay{

    public MyOverlay(){

    }   

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

    Paint   mPaint = new Paint();
        mPaint.setDither(true);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(2);

        GeoPoint gP1 = new GeoPoint(19240000,-99120000);
        GeoPoint gP2 = new GeoPoint(37423157, -122085008);

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

    Path    path = new Path();

    Projection  projection.toPixels(gP1, p1);
        projection.toPixels(gP2, p2);

        path.moveTo(p2.x, p2.y);
        path.lineTo(p1.x,p1.y);

        canvas.drawPath(path, mPaint);
    }

礼儀: Googleマップに線/パスを描く

2)これが私のために働いたものです:

createMarkers()
{ 
    for(elem:bigList)
    { 
        GeoPoint geoPoint = new GeoPoint((int)(elem.getLat()*1000000), (int) (elem.getLon()*1000000)); 
        OverlayItem overlayItem = new OverlayItem(geoPoint, elem.getName(), elem.getData()); 
        itemizedOverlay.addOverlay(overlayItem); 
    } 

    itemizedOverlay.populateNow(); 
    mapOverlays.add(itemizedOverlay); //outside of for loop 
} 

およびMyOverlay:

public void addOverlay(OverlayItem overlay) 
{ 
    m_overlays.add(overlay); 
} 

public void populateNow()
{
    populate(); 
}

礼儀:stackoverflow.com不明なリンク

3)最良の方法は、タイマークラスを使用することです。タイマークラスとその使用方法の非常に詳細な説明は、次のリンクにあります。

http://life.csu.edu.au/Java-tut/essential/threads/timer.html

4)私はこのコードを使用しました:

if(!mapOverlays.isEmpty()) 
{ 
    mapOverlays.clear(); 
    mapView.invalidate(); 
} 

これらの答えが少なくとも他の1人に役立つことを願っています。ありがとう。

11
Ahsan

私も同じ問題を抱えてる。私たちはiphoneアプリとAndroidアプリを同時に開発しています。2500以上のマップオーバーレイがあります。iphoneでは問題ありません。Android =すべてのオーバーレイを追加した後にpopulate()を呼び出すとき(もちろん、私の最初の試みは、オーバーレイを追加した後、毎回populate()を呼び出すことでした。これは、Googleのチュートリアルによる典型的な間違いです。 2500以上のオーバーレイがすべてItemizedOverlayに追加されました。)

したがって、htcヒーローデバイスで1回のpopulate()呼び出しが完了するまでに40秒以上かかります。私は忙しいインジケーターを入れなければなりませんでした。 Populate()の進行状況に関する情報を取得できないため、進行状況バーは使用できません。

別の解決策を試しました。ItemizedOverlayを使用せず、手動でオーバーレイを追加し、Overlayをサブクラス化します。結果:実際、これらすべてのオーバーレイをマップに追加する方がはるかに高速です。ただし、各オーバーレイでdraw()メソッドが常に呼び出されるため、マップは使用できなくなります。私の描画方法では、可能な限り最適化しようとしました。毎回ビットマップを作成するわけではありません。私のdraw()メソッドは次のようになります。

public void draw(Android.graphics.Canvas canvas, MapView mapView, boolean shadow)  {
// our marker bitmap already includes shadow.
// centerPoint is the geopoint where we need to put the marker.
 if (!shadow) {
  Point point = new Point();  
  mapView.getProjection().toPixels(centerPoint, point);
  canvas.drawBitmap(markerBitmap, point.x, point.y, null);
 }

}

ここでは、markerBitmapが事前に計算されています。他に何を最適化できるかわかりません。 ItemizedOverlayを使用していない場合、何らかのpopulate()呼び出しが必要ですか?そのための良い答えは見つかりませんでした。

今のところ、バックグラウンドスレッドで作成されたItemizedOverlayをキャッシュすることに頼っています。このようにして、少なくともユーザーは毎回待つ必要はありません。

2
winitzki

#2については、そこで何も解決したとは思いません。読みにくいコードは、マーカーをオーバーレイに配置する方法と、そのオーバーレイをマップに追加する方法を示しています。それはまさに私がそれをする方法です。私は約300のホテルの地図を持っており、NexusOneでマーカーを作成するのにAndroid何が起こっているかをユーザーに知らせるプログレスバー。

私はiPhoneにすでに存在するアプリに取り組んでいますが、iPhoneにはこれらの300以上のマーカーをほぼ瞬時に描画するのに問題はないようです。プログレスバーの存在を上司に説明するのは難しいでしょう。

誰かがこのプロセスを最適化する方法を知っているなら...私は感謝します。

これが私のコードです:

    ...
        for (int m = 0; m < ArrList.size(); m++) {
            tName = ArrList.get(m).get("name").toString();
            tId = ArrList.get(m).get("id").toString();
            tLat = ArrList.get(m).get("lat").toString();;
            tLng = ArrList.get(m).get("lng").toString();;
            try {
                lat = Double.parseDouble(tLat);
                lng = Double.parseDouble(tLng);
                p1 = new GeoPoint(
                        (int) (lat * 1E6), 
                        (int) (lng * 1E6));
                OverlayItem overlayitem = new OverlayItem(p1, tName, tId);
                itemizedoverlay.addOverlay(overlayitem);
            } catch (NumberFormatException e) {
                Log.d(TAG, "NumberFormatException" + e);    
            }
        } 

この文字列>二重変換を回避することで時間を節約できることはわかっていますが、それによって大幅な節約ができるとは思いません。

0
bobetko