安卓地图V2与安卓地图扩展一起添加大量标记非常缓慢

4
我正在使用android maps api v2和android-maps-extensions进行聚合,并将近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线程中执行!这是正确的吗?有没有办法在后台线程中添加这些标记?我该如何修复或解决问题?
附言:对不起我的英语不好,我正在同时学习Android和英语!! =D
谢谢
2个回答

0

除了将标记聚类或检查标记是否在地图的可见范围内之外,没有其他方法可以使绘图不阻塞用户界面,因为它们必须在用户界面线程上绘制。

很可能您不需要同时显示所有1000个标记,因此我建议检查标记是否在地图的可见边界内,并仅在该标记在其中时进行绘制。这样做可以使用单独的线程,但是您需要一个处理程序来回调主线程,当有需要绘制的标记时。


谢谢回复!集群框架已经在地图上绘制,只在可见区域内!我认为我不需要控制这个。但是使用后台线程仅处理可见区域中的标记的想法很有趣。如果我无法很好地使用集群框架,我会尝试这样做。谢谢 - Leandro Boni
@LeandroBoni 是的。Extensions 仅在使用 addMarkersDynamically 时,向可见区域添加市场。 - MaciejGórski
感谢确认!在添加标记后,集群表现得非常完美。问题是在地图显示时添加标记。我现在进行了一项小测试,只向地图添加了50个标记,阻塞仍然存在! - Leandro Boni

0
你的代码问题似乎是在循环中调用了publishProgress。相反,在onPostExecute中执行该循环。

谢谢回复。我尝试使用onPostExecute,但结果仍然相同。而且在地图未显示时使用publishProgress非常快!还有其他想法吗? - Leandro Boni
@LeandroBoni,你能准确地说出每个步骤所需的时间吗?比如将“从数据库中读取标记并在地图上添加所需的时间通常为800毫秒”分成两个时间,并解释它与“UI线程被阻塞3秒”的关系。 - MaciejGórski
我解决了问题!!这是我的一个基本错误!!我按照你说的做了,发现问题出在保存数据到SQLite中。我正在使用Volley框架进行请求,并且我认为回调也在另一个线程中执行,所以我一直在保存数据到数据库中。非常感谢你,伙计!!你帮了我很多...我该如何关闭这个答案?我是StackOverflow的新手!! - Leandro Boni
@LeandroBoni 在答案左侧应该有一个未填充的勾选标记,您可以单击它来接受答案为正确。此外,您可能希望随时单击指向上方的三角形(不仅限于您的问题),以表示答案或问题对您有用。 - MaciejGórski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接