使用Android-Maps-Extensions的Android Maps V2会非常慢地添加大量标记

时间:2014-01-07 19:52:10

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

我正在使用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读取并且它非常快,当显示地图时,标记已经在地图上没有任何延迟。 PERFECT !!

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

我试过这些东西:

  1. 在onPostExecute中添加标记
  2. 创建一次BitmapDescriptor
  3. 如何在不阻止UI线程的情况下添加标记?我已经在后台线程中进行了所有的读取和下载,但是需要在UI线程中执行添加标记!这是对的吗?有没有办法在后台线程中添加这些标记?如何修复或解决方法?

    P.s:抱歉因为我的英语不好,我正在学习机器人和英语! = d

    由于

2 个答案:

答案 0 :(得分:0)

除了聚类标记或检查标记是否在地图的可见边界内之外,没有办法使得绘图不会阻止UI,因为它们必须在UI线程上绘制。

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

答案 1 :(得分:0)

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