Google Maps API v2上的折线性能问题

时间:2014-05-29 15:19:07

标签: android google-maps google-maps-android-api-2 android-maps-v2 mapfragment

我正在编写一个Android应用程序,其中我必须代表某些块外观。为此,我为每个相关的块立面绘制折线(非常简单的折线,实际上是2个点线......)。

最糟糕的情况是,最多可能有10万条折线。

我的问题是我用大约3000行进行测试并且它已经非常慢了。获取要显示的数据没有问题,绘制线条没有问题,但绘制超过1k行时地图会变得迟钝。

我为每条折线创建一个PolylineOptions,然后绘制它并将其存储在如下变量中:

PolylineOptions options = new PolylineOptions();
options.add(latlon1, latlon2);
options.width(5);
options.color(Color.RED);
Polyline myPolyline = map.addPolyline(options);
myPolyline.setVisible(true);
myPolylines.add(myPolyline);

我尝试不存储它们(虽然这是后续处理所必需的),以防它是一个内存问题,但没有什么区别......而且,当存储它们时,应用程序的其余部分工作流畅(一些额外的按钮/文本字段),它只是变慢的地图(移动/缩放时)。

哦,我正在使用谷歌地图api v2的mapfragment类。

所以,问题是:有没有办法改善地图表现?

提前致谢。

编辑:折线一次全部可见。为了避免画出不必要的线条,我添加了一个"之前的步骤"其中我绘制圆圈,表示具有填充颜色(绿色到红色)的立面数量,并且仅在选择圆圈并且用户要求详细视图时显示线条。

EDIT2:这是我想要完成的事情(它来自地图指南地图,但我试图在Android上复制)facades

3 个答案:

答案 0 :(得分:1)

而不是一次性绘制所有内容,只绘制您可以看到的内容。

所以你会得到可见地图的界限

VisibleRegion vr = map.getProjection().getVisibleRegion();
bounds = vr.latLngBounds;

然后检查你的线是否在可见区域的边界内,然后绘制线

执行此操作将允许您在asynctask中运行代码,您可以使用处理程序回调主线程以在需要时绘制一条线。

您还必须覆盖onCameraChange以了解VisibleRegion何时更改,即。你模式地图。还有其他一些你需要做的事情,比如跟踪一条线是否被绘制,所以你不要多次绘制同一条线

答案 1 :(得分:1)

如果折线没有变化,我会在背景图块上绘制它们,而不是使用地图折线功能。

有关如何根据LatLng-Coordinates将形状绘制到切片中的示例,请参阅我对this SO question的回答

答案 2 :(得分:0)

我使用asynctask来创建每行50个坐标的polylineoption,并且在publishprogress方法中我将折线添加到地图中。如果确实运行时间过长而且我还没有进度,那么用户可以使用后退按钮取消任务。我最大的测试是来自sqllite数据库的3000坐标。但是,对于每个折线选项有两个坐标,这个代码会因调用publishprogress而陷入困境,因此您必须将两个坐标折线中的几十个堆叠起来,然后将它们添加到publishprogress方法中的地图中。 PublishProgress采用数组,因此传递50个折线选项并不困难。在使用每条折线50个坐标进行调试时,您可以看到在地图上绘制的折线。在实时模式中,折线仅在我便宜的50美元测试手机上出现。

注意:我将所有asynctasks作为单独的.java文件执行,因此我可以在构造函数中传递我需要的任何内容,因此我有相同的cancelMe()代码。我使用的大部分代码都在下面,我省略了数据库的内容,因为它对每个人都不同。

public class TaskParseKmldb extends AsyncTask<KmlSummary, PolylineOptions, Boolean>
        implements OnCancelListener {

public interface TaskParseKmldbCallback {
    void onTaskParseKmldbComplete(boolean success);
}


public TaskParseKmldb(Activity activity, KmlSummary kmlSummary, GoogleMap mMap,
            ProgressDialog pd) {
    this.activity = activity;
    this.kmlSummary = kmlSummary;
    this.mMap = mMap;
    this.pd = pd;
    // determine if calling activity has implemented the callback interface
    callback = (TaskParseKmldbCallback.class.isAssignableFrom(activity
.getClass())) ? (TaskParseKmldbCallback) activity : null;   
    }

...为onCanceled例程设置进程对话框侦听器。

@Override
    protected void onPreExecute() {
        pd.setOnCancelListener(this);
        pd.setMessage("Loading Recorded Route...");
        pd.show();
    }


@Override
protected void onCancelled(Boolean result) {
    if (pd != null) {
        pd.dismiss();
        pd = null;
    }
    if (callback != null) {
        callback.onTaskParseKmldbComplete(result);
    }
}

@Override
    public void onCancel(DialogInterface dialog) {
        cancelMe(); // this just gracefully cancels the task.
    }

public void cancelMe() {
    if (!getStatus().equals(Status.FINISHED)) {
        // not canceled
        if (!isCancelled()) {
            cancel(false);
            try {
                get();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (CancellationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

...在doInBackground中的某个地方

if (progress.getPoints().size() > 0) {
                publishProgress(progress);
                ret = true;
            }


protected void onProgressUpdate(PolylineOptions... progress) {
        if (isCancelled()) {
            return;
        }
        if (progress[0] != null) {
            // add the poly line to the map
            // save the polyline returned by the map for later use
            polylines.add(mMap.addPolyline(progress[0]));
        }
    }

...

@Override
protected void onPostExecute(Boolean result) {

    if (pd != null) {
        pd.dismiss();
        pd = null;
    }