谷歌地图v2 Projection.toScreenLocation(...)非常慢

时间:2014-10-06 12:00:13

标签: java android performance google-maps android-maps-v2

我已在我的Android应用程序中将Google Maps v1升级到v2。

v2很不错,但是一种方法似乎是我生命中最慢的方法。

Projection proj = map.getProjection();
Point point = proj.toScreenLocation(example.m_geopoint);

toScreenLocation(...)是如此之慢,因此应用程序减慢到无法使用的慢动作。 该方法每帧更新可能100次,但在Google Maps v1上的效果非常好。

当我登录Android控制台时,我看到了:

10-06 13:53:04.460: D/dalvikvm(4889): GC_EXPLICIT freed 251K, 14% free 14622K/16839K, paused 3ms+5ms
10-06 13:53:05.859: D/dalvikvm(4889): GC_EXPLICIT freed 252K, 14% free 14622K/16839K, paused 2ms+5ms
10-06 13:53:07.222: D/dalvikvm(4889): GC_EXPLICIT freed 251K, 14% free 14622K/16839K, paused 3ms+6ms
...

调用该方法时,此消息一直在显示。

v2和v1之间的区别是:

pointOut = proj.toScreenLocation(geopointIn); // v2
projection.toPixels(geopointIn, pointOut); // v1

v1似乎是更优化的解决方案。有没有办法让它更快?这是性能错误吗?

2 个答案:

答案 0 :(得分:1)

我来晚了很晚,但是我使用android.graphics.Matrix有一个答案:

float getYMercator(double latitude){
    return (float)Math.log(Math.tan(Math.PI*(0.25+latitude/360.0)));
}
float [] fastToScreenLocation(GoogleMap map, List<LatLng> coordinates,int viewHeight, int viewWidth){
    VisibleRegion visibleRegion = map.getProjection().getVisibleRegion();
    Matrix transformMatrix = new Matrix();
    boolean ok = transformMatrix.setPolyToPoly(
            new float[] {
                    (float)visibleRegion.farLeft.longitude, getYMercator(visibleRegion.farLeft.latitude),
                    (float)visibleRegion.farRight.longitude, getYMercator(visibleRegion.farRight.latitude),
                    (float)visibleRegion.nearRight.longitude, getYMercator(visibleRegion.nearRight.latitude),
                    (float)visibleRegion.nearLeft.longitude, getYMercator(visibleRegion.nearLeft.latitude)
            },0,
            new float[] {
                    0, 0,
                    viewWidth, 0,
                    viewWidth,viewHeight,
                    0, viewHeight
            }, 0,
            4);
    if(!ok) return null;
    float[] points = new float[2*coordinates.size()];
    for(int i=0;i<coordinates.size();++i){
        LatLng location = coordinates.get(i);
        points[2*i]=(float)location.longitude;
        points[2*i+1]=getYMercator(location.latitude);
    }
    transformMatrix.mapPoints(points);
    return points;
}

基本上,它将LatLng投影到伪WebMercator坐标(将WebMercator坐标进行线性转换以节省一些计算)。然后,它计算必要的矩阵以将可见区域转换为屏幕坐标,并将找到的矩阵应用于坐标列表中的点。与测试相比,三星J3上的150个坐标列表的测试速度大约快了300倍(避免多次调用时重新分配数组)。

答案 1 :(得分:0)

这个答案可能为时已晚,但如果其他人遇到同样的问题,像我一样,解决方案可能是使用Java的Graphics2D在自己的服务器上预渲染图像(其工作方式几乎与绘制到canvas)并在应用程序中下载它。您必须将地理点转换为笛卡尔坐标。 在应用内,您只需将图像定位为具有LatLngBounds的GroundOverlay:https://developers.google.com/maps/documentation/android/groundoverlay#use_latlngbounds_to_position_an_image

并将其添加到地图中... https://developers.google.com/maps/documentation/android/groundoverlay#change_an_overlay

对我来说,这种方法非常快。至少与Google Maps V1方法一样快。