【问题标题】:Android Maps V2 with Android-Maps-Extensions add lots of markers very slow带有 Android-Maps-Extensions 的 Android Maps V2 添加大量标记非常缓慢
【发布时间】:2014-01-25 15:50:55
【问题描述】:

我正在使用带有 android-maps-extensions 的 android maps api v2 进行集群,并向地图添加近 1000 个标记。在应用程序的第一次运行中,我使用后台线程从 web 服务下载数据并保存在 SQLite 中,然后将标记添加到地图中。当我在显示地图时在地图上添加这些标记时,ui 线程在 3 秒内被阻塞,在此期间无法移动地图并且我使用的进度条也停止。

这是我用来在地图上添加标记的代码:

private class ReadMarkersFromDB extends AsyncTask<String, UpdateEstacionamentoMap, ArrayList<UpdateEstacionamentoMap>> {

    @Override
    protected ArrayList<UpdateEstacionamentoMap> doInBackground(String... params) {

        EstacionamentoDAO estacionamentoDAO = new EstacionamentoDAO();

        SQLiteHelper sqh = new SQLiteHelper(getApplicationContext());
        SQLiteDatabase sqdb = sqh.getWritableDatabase();

        //Caso tenha informado a string para seleção, usa
        String selection = "";
        if(params[0] != null && !params[0].isEmpty())
        {
            selection = params[0];
        }

        //Pega todos os estacionamentos
        ArrayList<Estacionamento> estacionamentos = estacionamentoDAO.get(sqdb,selection);

        sqdb.close();
        sqh.close();

        //Armazena o que deve ser feito no mapa. Operações: Excluir, Incluir ou Atualizar os estacionamentos
        ArrayList<UpdateEstacionamentoMap> atualizarMapa = new ArrayList<UpdateEstacionamentoMap>();

        //Se não passou nenhuma string para seleção, logo retornou todos os registros e no mapa não tem nada, portanto somente inclui tudo no mapa
        if(selection == null || selection.isEmpty())
        {
            //Itera os estacionamentos retornados na consulta
            for(Estacionamento estacAux : estacionamentos)
            {
                //AQUI É ONDE MANDA INCLUIR O PIN NO MAPA
                publishProgress(new UpdateEstacionamentoMap(estacAux,null,0)); //0 = Incluir Pin do Estacionamento
            }
        }else //Se passou algum "selection" assume que já tem coisas no mapa e precisa apenas atualizar o conteúdo já existente no mapa
        {
            ...
        }

        return atualizarMapa;
    }

    @Override
    protected void onProgressUpdate(UpdateEstacionamentoMap... updateEstac)
    {
        if(updateEstac[0].operacao == 0) //Incluir pin no mapa 
        {
            //AQUI É ONDE INCLUI O PIN NO MAPA
            if(!updateEstac[0].estac.getDeletado()) //Inclui no mapa se o estacionamento não estiver deletado
                map.addMarker(options.data(updateEstac[0].estac).position(updateEstac[0].estac.getLocation()).title(updateEstac[0].estac.getNome()).snippet(updateEstac[0].estac.getEndereco()).icon(icon));
        }
        else
        {
        ...
        }

    }

    @Override
    protected void onPostExecute(ArrayList<UpdateEstacionamentoMap> estacionamentos) {


    }
}

我正在使用 addMarkersDinamically:

ClusteringSettings clusteringSettings = new ClusteringSettings().clusterOptionsProvider(new MyClusterOptionsProvider(getResources()));
clusteringSettings.addMarkersDynamically(true); //Adiciona os pins somente na região visível pelo usuário

double clusterSize = 70; //Configuração para considerar dois pontos um cluster
clusteringSettings.clusterSize(clusterSize);

map.setClustering(clusteringSettings);

问题只出现在第一次运行!!下载数据后,当应用程序打开时,我从 SQLite 读取,速度非常快,当显示地图时,标记已经在地图上,没有任何延迟。完美!!

我认为问题在于在地图显示后将标记放在地图上。我看到从数据库读取标记并添加到地图上的时间通常是 800 毫秒。

我试过这些东西:

  1. 在 onPostExecute 中添加标记
  2. 创建一次 BitmapDescriptor

如何使这些添加标记不阻塞 UI 线程?我已经在后台线程中完成了所有读取和下载,但是添加标记需要在 UI 线程中执行!这是正确的吗?有没有办法在后台线程中添加这些标记?如何修复或解决问题?

P.s:对不起,因为我的英语不好,我正在同时学习安卓和英语!! =D

谢谢

【问题讨论】:

    标签: android google-maps-markers google-maps-android-api-2 android-maps-v2 android-maps-extensions


    【解决方案1】:

    您的代码的问题似乎是循环调用 publishProgress。而是在 onPostExecute 中执行该循环。

    【讨论】:

    • 感谢回复。我尝试使用 onPostExecute 但结果是一样的。并且在未显示地图时与 publishProgress 一起使用非常快!还有其他想法吗?
    • @LeandroBoni 你能准确地说出什么需要多少时间吗?就像将time spend to read markers from DB **and** add on the map is usually 800 ms 分成两次,它与ui thread is blocked during 3 seconds 有什么关系。
    • 我解决了这个问题!!这是我的一个基本错误!我按照你说的做了,我发现问题出在 SQLite 中的保存数据上。我正在使用 Volley 框架来执行请求,并且我认为回调也在另一个线程中执行,所以我将数据保存到 DB。非常感谢大佬!!你帮了我很多..我怎样才能关闭这个答案?我是 StackOverflow 的新手!!
    • @LeandroBoni 在答案的左侧应该有一个未填充的勾号,您单击以接受正确的答案。此外,您可能希望随时单击指向上方的三角形(不仅是在您的问题上)以表明答案或问题对您有用。
    【解决方案2】:

    没有办法(除了对标记进行聚类或检查标记是否在地图的可见范围内)使绘图不会阻塞 UI,因为它们必须在 UI 线程上绘制。

    您可能不需要一次显示所有 1000 个标记,因此我会检查标记是否在地图的可见边界内,如果是则仅绘制该标记。这样做你可以使用一个单独的线程,但是当你需要绘制一个标记时,你需要一个处理程序来回调主线程

    【讨论】:

    • 感谢您的回复!!集群框架已经在地图上仅在可见区域绘制!!我想我不需要控制这个。但是使用后台线程仅处理可见区域中的引脚的想法很有趣。如果我不能很好地使用集群框架,我会试试这个。谢谢
    • @LeandroBoni 是的。当您动态使用 addMarkers 时,扩展程序只会在可见区域添加市场。
    • 感谢您的确认!!添加标记后,集群完美无缺。问题是在显示地图时添加标记。我现在做了一个小测试,只在地图上添加了 50 个标记,该块仍然存在!
    猜你喜欢
    • 2012-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-25
    • 2014-11-30
    • 2015-11-23
    • 1970-01-01
    相关资源
    最近更新 更多